GCC Code Coverage Report


Directory: src/athena/
File: src/athena/athena_network_sub.f90
Date: 2026-04-15 16:08:59
Exec Total Coverage
Lines: 1078 1814 59.4%
Functions: 2 2 100.0%
Branches: 3893 13358 29.1%

Line Branch Exec Source
1 submodule(athena__network) athena__network_submodule
2 !! Submodule containing implementations for the network module
3 #ifdef _OPENMP
4 use omp_lib
5 #endif
6 use coreutils, only: stop_program, print_warning, to_lower
7 use athena__misc_ml, only: shuffle
8
9 use athena__accuracy, only: categorical_score, mae_score, mse_score, r2_score
10 use athena__base_layer, only: learnable_layer_type, merge_layer_type
11 #if defined(GFORTRAN)
12 use athena__container_layer, only: container_reduction
13 #endif
14
15 use athena__container_layer, only: &
16 list_of_layer_types, allocate_list_of_layer_types, &
17 list_of_onnx_layer_creators, allocate_list_of_onnx_layer_creators
18
19 ! Layer types
20 use athena__flatten_layer, only: flatten_layer_type
21 use athena__add_layer, only: add_layer_type
22 use athena__concat_layer, only: concat_layer_type
23 use athena__input_layer, only: input_layer_type
24 use athena__msgpass_layer, only: msgpass_layer_type
25 use athena__recurrent_layer, only: recurrent_layer_type
26
27 ! #ifdef _OPENMP
28 ! !$omp declare reduction( &
29 ! !$omp& network_reduction : network_type:omp_out%network_reduction(omp_in)) &
30 ! !$omp& initialiser(omp_priv = omp_orig)
31 ! #endif
32
33 contains
34
35 !###############################################################################
36 1 module subroutine network_reduction(this, source)
37 !! Procedure to add two networks together
38 implicit none
39
40 ! Arguments
41 class(network_type), intent(inout) :: this
42 !! Instance of network
43 type(network_type), intent(in) :: source
44 !! Instance of network to be added to this
45
46 ! Local variables
47 integer :: i
48 !! Loop index
49
50 1 this%metrics(1)%val = this%metrics(1)%val + source%metrics(1)%val
51 1 this%metrics(2)%val = this%metrics(2)%val + source%metrics(2)%val
52
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 do i=1,size(this%model)
53 1 select type(layer_this => this%model(i)%layer)
54 class is(learnable_layer_type)
55 select type(layer_source => source%model(i)%layer)
56 class is(learnable_layer_type)
57 2 call layer_this%reduce(layer_source)
58 end select
59 end select
60 end do
61
62 1 end subroutine network_reduction
63 !###############################################################################
64
65
66 !###############################################################################
67 1 module subroutine network_copy(this, source)
68 !! Procedure to copy a network
69 implicit none
70
71 ! Arguments
72 class(network_type), intent(inout) :: this
73 !! Instance of network
74 type(network_type), intent(in), target :: source
75 !! Instance of network to be copied
76
77 ! Local variables
78 integer :: i
79 !! Loop index
80
81
82
6/10
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
3 this%metrics = source%metrics
83
18/156
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 3 times.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✓ Branch 98 taken 3 times.
✓ Branch 99 taken 1 times.
✓ Branch 100 taken 3 times.
✗ Branch 101 not taken.
✓ Branch 102 taken 3 times.
✗ Branch 103 not taken.
✓ Branch 105 taken 3 times.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✓ Branch 108 taken 3 times.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 112 not taken.
✓ Branch 113 taken 3 times.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 160 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
8 this%model = source%model
84 1 this%num_layers = source%num_layers
85 1 this%batch_size = source%batch_size
86 1 this%num_params = source%num_params
87 1 this%num_outputs = source%num_outputs
88
3/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1 this%optimiser = source%optimiser
89
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✓ Branch 23 taken 1 times.
4 this%vertex_order = source%vertex_order
90
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✓ Branch 23 taken 1 times.
2 this%root_vertices = source%root_vertices
91
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✓ Branch 23 taken 1 times.
2 this%leaf_vertices = source%leaf_vertices
92
3/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1 this%loss = source%loss
93 1 this%get_accuracy => source%get_accuracy
94
28/64
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 3 times.
✓ Branch 21 taken 1 times.
✓ Branch 22 taken 3 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 2 times.
✓ Branch 27 taken 1 times.
✓ Branch 28 taken 2 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✓ Branch 33 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 1 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 1 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 1 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 1 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✓ Branch 57 taken 1 times.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
8 this%auto_graph = source%auto_graph
95
96 1 end subroutine network_copy
97 !###############################################################################
98
99
100 !##############################################################################!
101 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
102 !##############################################################################!
103
104
105 !###############################################################################
106 108 module subroutine build_vertex_order(this)
107 !! Generate the order of the layers in the network
108 !!
109 !! This module contains the subroutine to generate the order of the layers
110 !! in the network. The order is generated by depth first search (DFS) on the
111 !! graph of the network.
112 implicit none
113
114 ! Arguments
115 class(network_type), intent(inout) :: this
116 !! Instance of network
117
118 ! Local variables
119 integer :: i, order_index
120 !! Loop index
121 216 logical, dimension(this%auto_graph%num_vertices) :: visited
122 !! Array to store whether a vertex has been
123
124
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 108 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 108 times.
✓ Branch 9 taken 280 times.
✓ Branch 10 taken 108 times.
388 visited = .false.
125
3/4
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
108 if(allocated(this%vertex_order)) deallocate(this%vertex_order)
126
13/24
✓ Branch 0 taken 108 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 108 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 108 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 108 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 108 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 108 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 108 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 108 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 108 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 108 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 108 times.
✓ Branch 29 taken 280 times.
✓ Branch 30 taken 108 times.
388 allocate(this%vertex_order(this%auto_graph%num_vertices), source=0)
127
128 108 order_index = 0
129
2/2
✓ Branch 0 taken 280 times.
✓ Branch 1 taken 108 times.
388 do i = this%auto_graph%num_vertices, 1, -1
130
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 280 times.
✓ Branch 6 taken 208 times.
✓ Branch 7 taken 72 times.
280 if(.not.visited(i)) call this%dfs( &
131 i, visited, this%vertex_order, order_index &
132 316 )
133 end do
134
135 108 end subroutine build_vertex_order
136 !###############################################################################
137
138
139 !###############################################################################
140 280 recursive module subroutine dfs( &
141 280 this, vertex_index, visited, order, order_index &
142 )
143 !! Depth first search algorithm
144 implicit none
145
146 ! Arguments
147 class(network_type), intent(in) :: this
148 !! Instance of network
149 integer, intent(in) :: vertex_index
150 !! Index of the vertex to start the search from
151 logical, dimension(this%auto_graph%num_vertices), intent(inout) :: visited
152 !! Array to store whether a vertex has been visited
153 integer, dimension(this%auto_graph%num_vertices), intent(inout) :: order
154 !! Array to store the order of the vertices
155 integer, intent(inout) :: order_index
156 !! Index of the current vertex in the order array
157
158 ! Local variables
159 integer :: i
160 !! Loop index
161
162
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 280 times.
280 visited(vertex_index) = .true.
163
2/2
✓ Branch 0 taken 884 times.
✓ Branch 1 taken 280 times.
1164 do i = 1, this%auto_graph%num_vertices, 1
164
6/10
✗ Branch 0 not taken.
✓ Branch 1 taken 884 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 884 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 884 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 884 times.
✓ Branch 12 taken 172 times.
✓ Branch 13 taken 712 times.
1164 if(this%auto_graph%adjacency(i,vertex_index).ne.0)then
165
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 172 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 172 times.
✓ Branch 6 taken 72 times.
✓ Branch 7 taken 100 times.
172 if(.not.visited(i)) call this%dfs(i, visited, order, order_index)
166 end if
167 end do
168 280 order_index = order_index + 1
169
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 280 times.
280 order(order_index) = vertex_index
170
171 280 end subroutine dfs
172 !###############################################################################
173
174
175 !###############################################################################
176 54 module subroutine build_root_vertices(this)
177 !! Calculate the root vertices of the network
178 implicit none
179
180 ! Arguments
181 class(network_type), intent(inout) :: this
182 !! Instance of network
183
184 ! Local variables
185 integer :: i
186 !! Loop index
187
188
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
54 if(allocated(this%root_vertices)) deallocate(this%root_vertices)
189
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
54 allocate(this%root_vertices(0))
190 ! from = 1
191
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 54 times.
141 do i = 1, this%auto_graph%num_vertices
192
12/18
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 87 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 87 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 87 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 87 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 87 times.
✓ Branch 18 taken 158 times.
✓ Branch 19 taken 54 times.
✓ Branch 20 taken 33 times.
✓ Branch 21 taken 125 times.
✓ Branch 22 taken 54 times.
✓ Branch 23 taken 33 times.
266 if(all(this%auto_graph%adjacency(:,i).eq.0))then
193
14/24
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 54 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 54 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 54 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 54 times.
✓ Branch 19 taken 54 times.
✓ Branch 20 taken 54 times.
✓ Branch 21 taken 54 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 54 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 54 times.
✓ Branch 27 taken 54 times.
✓ Branch 28 taken 54 times.
162 this%root_vertices = [this%root_vertices, i]
194 ! to = from + this%model(i)layer%num_input_data - 1
195 ! this%root_bounds = [ this%root_bounds, reshape([from,to], [2,1]) ]
196 ! from = to + 1
197 end if
198 end do
199 54 end subroutine build_root_vertices
200 !###############################################################################
201
202
203 !###############################################################################
204 54 module subroutine build_leaf_vertices(this)
205 !! Calculate the output vertices of the network
206 implicit none
207
208 ! Arguments
209 class(network_type), intent(inout) :: this
210 !! Instance of network
211
212 ! Local variables
213 integer :: i
214 !! Loop index
215
216
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
54 if(allocated(this%leaf_vertices)) deallocate(this%leaf_vertices)
217
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
54 allocate(this%leaf_vertices(0))
218
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 54 times.
194 do i = 1, this%auto_graph%num_vertices
219
12/18
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 140 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 140 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 140 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 140 times.
✓ Branch 18 taken 308 times.
✓ Branch 19 taken 54 times.
✓ Branch 20 taken 86 times.
✓ Branch 21 taken 222 times.
✓ Branch 22 taken 54 times.
✓ Branch 23 taken 86 times.
416 if(all(this%auto_graph%adjacency(i,:).eq.0))then
220
14/24
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 54 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 54 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 54 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 54 times.
✓ Branch 19 taken 54 times.
✓ Branch 20 taken 54 times.
✓ Branch 21 taken 54 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 54 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 54 times.
✓ Branch 27 taken 54 times.
✓ Branch 28 taken 54 times.
162 this%leaf_vertices = [this%leaf_vertices, i]
221 end if
222 end do
223 54 end subroutine build_leaf_vertices
224 !###############################################################################
225
226
227
228
229
230 !##############################################################################!
231 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
232 !##############################################################################!
233
234
235 !###############################################################################
236 1 module subroutine print(this, file)
237 !! Print the network to a file
238 use coreutils, only: to_upper
239 use athena__io_utils, only: athena__version__
240 implicit none
241
242 ! Arguments
243 class(network_type), intent(in) :: this
244 !! Instance of network
245 character(*), intent(in) :: file
246 !! File to print the network to
247
248 ! Local variables
249 integer :: l, v, e, vertex_index, unit
250 !! Loop index
251 integer :: operator_in, operator_out
252 !! Operators for the layer
253 character(3) :: operator_str
254 !! String to store the operator
255 character(256) :: suffix, fmt
256 !! Suffix for the layer
257 1 integer, dimension(:), allocatable :: input_list, output_list
258
259 1 open(newunit=unit,file=file,status='replace')
260
261 1 write(unit,'("NETWORK_SETTINGS")')
262 1 write(unit,'(3X,"ATHENA_VERSION = ",A)') trim(adjustl(athena__version__))
263
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 if(allocated(this%name)) write(unit,'(3X,"NAME = ",A)') trim(adjustl(this%name))
264 1 write(unit,'(3X,"EPOCH = ",I0)') this%epoch
265 1 write(unit,'(3X,"BATCH_SIZE = ",I0)') this%batch_size
266 1 write(unit,'(3X,"ACCURACY = ",F0.9)') this%accuracy_val
267 1 write(unit,'(3X,"LOSS = ",F0.9)') this%loss_val
268
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(allocated(this%accuracy_method))then
269
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 write(unit,'(3X,"ACCURACY_METHOD = ",A)') trim(adjustl(this%accuracy_method))
270 end if
271
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(allocated(this%loss_method))then
272
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 write(unit,'(3X,"LOSS_METHOD = ",A)') trim(adjustl(this%loss_method))
273 end if
274
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(allocated(this%optimiser))then
275
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 write(unit,'(3X,"OPTIMISER: ",A)') trim(adjustl(this%optimiser%name))
276 1 call this%optimiser%print_to_unit(unit=unit)
277 1 write(unit,'(3X,"END OPTIMISER")')
278 end if
279 1 write(unit,'("END NETWORK_SETTINGS")')
280
281
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 do v = 1, size(this%vertex_order,dim=1), 1
282
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 l = this%vertex_order(v)
283 3 operator_in = -1
284 3 operator_out = -1
285
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
3 allocate(input_list(0), output_list(0))
286
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 do e = 1, this%auto_graph%num_edges
287
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 4 times.
6 if(-this%auto_graph%edge(e)%index(2).eq.l)then
288
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
2 if(operator_in.gt.0.and.this%auto_graph%edge(e)%id.ne.operator_in)then
289 write(0,*) "WARNING: multiple operators for layer ", l
290 write(0,*) " using operator ", this%auto_graph%edge(e)%id
291 end if
292
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 operator_in = this%auto_graph%edge(e)%id
293 vertex_index = &
294
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 3 times.
✓ Branch 20 taken 2 times.
✓ Branch 21 taken 1 times.
3 findloc( this%vertex_order, this%auto_graph%edge(e)%index(1), 1 )
295
14/24
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✓ Branch 19 taken 2 times.
✓ Branch 20 taken 2 times.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 2 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 2 times.
✓ Branch 27 taken 2 times.
✓ Branch 28 taken 2 times.
6 input_list = [ input_list, vertex_index ]
296 end if
297
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 4 times.
9 if(this%auto_graph%edge(e)%index(1).eq.l)then
298
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
2 if(operator_out.gt.0.and.this%auto_graph%edge(e)%id.ne.operator_out)then
299 write(0,*) "WARNING: multiple operators for layer ", l
300 write(0,*) " using operator ", this%auto_graph%edge(e)%id
301 end if
302
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 operator_in = this%auto_graph%edge(e)%id
303 vertex_index = &
304
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 12 taken 6 times.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 6 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 6 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 6 times.
8 findloc( this%vertex_order, this%auto_graph%edge(e)%index(2), 1 )
305
14/24
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✓ Branch 19 taken 2 times.
✓ Branch 20 taken 2 times.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 2 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 2 times.
✓ Branch 27 taken 2 times.
✓ Branch 28 taken 2 times.
6 output_list = [ output_list, vertex_index ]
306 end if
307 end do
308
309 3 suffix = ""
310 3 select case(operator_in)
311 case(1)
312 3 operator_str = " ||"
313 case(2)
314 operator_str = " +"
315 case(3)
316
1/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 operator_str = " *"
317 end select
318 ! get size of input_list and make the formatted string
319
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if(size(input_list).eq.0)then
320
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 write(suffix,'(A," []")') trim(operator_str)
321 else
322 2 write(fmt,'("(A,A,"" ["",",I0,"(1X,I0),"" ]"")")') size(input_list)
323
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 write(suffix,fmt) trim(suffix), operator_str, input_list
324 end if
325 ! select case(operator_out)
326 ! case(1)
327 ! operator_str = " ||"
328 ! case(2)
329 ! operator_str = " +"
330 ! case(3)
331 ! operator_str = " *"
332 ! end select
333 ! if(size(output_list).gt.0)then
334 ! write(fmt,'("(A,A,"" ["",",I0,"(1X,I0),"" ]"")")') size(output_list)
335 ! write(suffix,fmt) trim(suffix), operator_str, output_list
336 ! end if
337
338
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
3 write(unit,'(A,A)') to_upper(trim(this%model(l)%layer%name)), trim(suffix)
339
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 call this%model(l)%layer%print(unit=unit, print_header_footer=.false.)
340
341
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
3 write(unit,'("END ",A)') to_upper(trim(this%model(l)%layer%name))
342
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
4 deallocate(input_list, output_list)
343 end do
344 1 close(unit)
345
346
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
2 end subroutine print
347 !###############################################################################
348
349
350 !###############################################################################
351 1 module subroutine read(this, file)
352 !! Read the network from a file
353 use coreutils, only: icount
354 implicit none
355
356 ! Arguments
357 class(network_type), intent(inout) :: this
358 !! Instance of network
359 character(*), intent(in) :: file
360 !! File to read the network from
361
362 ! Local variables
363 integer :: i, unit, stat, itmp1
364 !! Loop index
365 1 integer, dimension(:), allocatable :: input_list, output_list
366 !!! List of input and output layers
367 character(256) :: buffer, err_msg, input_str, output_str
368 !! Buffer for reading lines from file
369 character(20) :: name
370 !! Name of the layer
371 character(2) :: operator_in, operator_out
372 !! Operator for the layer
373 integer :: layer_index
374 !! Index of the layer in the list of layer types
375
376
377 1 if(.not.allocated(list_of_layer_types))then
378 1 call allocate_list_of_layer_types()
379 end if
380
381 1 open(newunit=unit,file=file,action='read')
382 1 i = 0
383 4 card_loop: do
384 5 i = i + 1
385 5 read(unit,'(A)',iostat=stat) buffer
386
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if(stat.lt.0)then
387 1 exit card_loop
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 elseif(stat.gt.0)then
389 call stop_program("error encountered in network read")
390 return
391 end if
392
2/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 if(trim(adjustl(buffer)).eq."") cycle card_loop
393
394 !! check if a tag line
395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(scan(buffer,'=').ne.0)then
396 write(0,*) "WARNING: unexpected line in read file"
397 write(0,*) trim(buffer)
398 write(0,*) " skipping..."
399 cycle card_loop
400 end if
401
402 !! check for card
403
4/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
4 name = trim(adjustl(buffer(1:scan(buffer,' ')-1)))
404
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if(name.eq."NETWORK_SETTINGS")then
405 1 call this%read_network_settings(unit)
406 1 cycle card_loop
407 end if
408
4/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
3 buffer = trim(adjustl(buffer(scan(buffer,' ')+1:)))
409
4/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
3 operator_in = trim(adjustl(buffer(1:scan(buffer,' ')-1)))
410
4/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
3 buffer = trim(adjustl(buffer(scan(buffer,' ')+1:)))
411
4/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
3 input_str = trim(adjustl(buffer(1:scan(buffer,']'))))
412
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(scan(input_str,'[').ne.0)then
413 input_str = &
414
9/12
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✓ Branch 15 taken 1 times.
3 trim(adjustl(input_str(scan(input_str,'[')+1:scan(input_str,']')-1)))
415 3 itmp1 = icount(input_str)
416
9/14
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
3 allocate(input_list(itmp1))
417 3 read(input_str,*) input_list
418 else
419 allocate(input_list, source = [-1])
420 end if
421
4/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 buffer = trim(adjustl(buffer(scan(buffer,']')+1:)))
422
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 operator_out = trim(adjustl(buffer(1:scan(buffer,' ')-1)))
423
4/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 buffer = trim(adjustl(buffer(scan(buffer,' ')+1:)))
424
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 output_str = trim(adjustl(buffer(1:scan(buffer,']'))))
425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(scan(output_str,'[').ne.0)then
426 output_str = &
427 trim(adjustl(output_str(scan(output_str,'[')+1:scan(output_str,']')-1)))
428 itmp1 = icount(output_str)
429 allocate(output_list(itmp1))
430 read(output_str,*) output_list
431 else
432
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
3 allocate(output_list(0))
433 end if
434
2/4
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
3 name = trim(adjustl(to_lower(name)))
435 layer_index = &
436 findloc( &
437 [ list_of_layer_types(:)%name ], &
438 name, &
439 dim = 1 &
440
10/16
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✓ Branch 11 taken 99 times.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✓ Branch 15 taken 99 times.
✓ Branch 16 taken 3 times.
201 )
441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(layer_index.eq.0)then
442 write(err_msg,'("unrecognised card ''",A)') trim(adjustl(buffer))
443 call stop_program(err_msg)
444 return
445 end if
446 call this%add( &
447 list_of_layer_types(layer_index)%read_ptr(unit), &
448 input_list = input_list, &
449 operator = operator_in &
450
7/50
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✓ Branch 44 taken 3 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 3 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 3 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 3 times.
✗ Branch 52 not taken.
3 )
451
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if(allocated(input_list)) deallocate(input_list)
452
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if(allocated(output_list)) deallocate(output_list)
453 end do card_loop
454 1 close(unit)
455
456
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
2 end subroutine read
457 !###############################################################################
458
459
460 !###############################################################################
461 1 module subroutine read_network_settings(this, unit)
462 !! Read the network settings from a file
463 use athena__tools_infile, only: assign_val, assign_vec
464 use coreutils, only: to_lower, to_upper, icount
465 implicit none
466
467 ! Arguments
468 class(network_type), intent(inout) :: this
469 !! Instance of network
470 integer, intent(in) :: unit
471 !! File unit
472
473 ! Local variables
474 integer :: stat
475 !! File status
476 integer :: itmp1
477 !! Temporary integer
478 character(20) :: accuracy_method, loss_method
479 !! Methods for accuracy and loss
480 character(256) :: buffer, tag, err_msg, name_
481 !! Buffer for reading lines, tag for identifying lines, error message
482
483
484 ! Loop over tags in layer card
485 !---------------------------------------------------------------------------
486 1 accuracy_method = ""
487 1 loss_method = ""
488 9 tag_loop: do
489
490 ! Check for end of file
491 !------------------------------------------------------------------------
492 10 read(unit,'(A)',iostat=stat) buffer
493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if(stat.ne.0)then
494 write(err_msg,'("file encountered error (EoF?) before END ",A)') &
495 to_upper(this%name)
496 call stop_program(err_msg)
497 return
498 end if
499
2/4
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
10 if(trim(adjustl(buffer)).eq."") cycle tag_loop
500
501 ! Check for end of layer card
502 !------------------------------------------------------------------------
503
3/4
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 9 times.
10 if(trim(adjustl(buffer)).eq."END NETWORK_SETTINGS")then
504 1 backspace(unit)
505 1 exit tag_loop
506 end if
507
508
2/4
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
9 tag=trim(adjustl(buffer))
509
6/10
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
9 if(scan(buffer,"=").ne.0) tag=trim(tag(:scan(tag,"=")-1))
510
6/10
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
9 if(scan(buffer,":").ne.0) tag=trim(tag(:scan(tag,":")-1))
511
512 ! Read parameters from save file
513 !------------------------------------------------------------------------
514 19 select case(trim(tag))
515 case("ATHENA_VERSION")
516 ! Ignore this tag, it is only for information
517 case("NAME")
518 1 call assign_val(buffer, name_, itmp1)
519
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 if(len(trim(adjustl(name_))) .gt. 0)then
520
4/10
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
1 this%name = trim(adjustl(name_))
521 end if
522 case("EPOCH")
523 1 call assign_val(buffer, this%epoch, itmp1)
524 case("BATCH_SIZE")
525 1 call assign_val(buffer, this%batch_size, itmp1)
526 case("ACCURACY")
527 1 call assign_val(buffer, this%accuracy_val, itmp1)
528 case("LOSS")
529 1 call assign_val(buffer, this%loss_val, itmp1)
530 case("ACCURACY_METHOD")
531 1 call assign_val(buffer, accuracy_method, itmp1)
532 1 call this%set_accuracy(accuracy_method)
533 case("LOSS_METHOD")
534 1 call assign_val(buffer, loss_method, itmp1)
535 1 call this%set_loss(loss_method)
536 case("OPTIMISER")
537 1 backspace(unit)
538 1 call this%read_optimiser_settings(unit)
539 case default
540 ! Don't look for "e" due to scientific notation of numbers
541 ! ... i.e. exponent (E+00)
542 if(scan(to_lower(trim(adjustl(buffer))),&
543 'abcdfghijklmnopqrstuvwxyz').eq.0)then
544 cycle tag_loop
545 elseif(tag(:3).eq.'END')then
546 cycle tag_loop
547 end if
548 write(err_msg,'("Unrecognised line in input file: ",A)') &
549 trim(adjustl(buffer))
550 call stop_program(err_msg)
551
10/12
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
18 return
552 end select
553 end do tag_loop
554
555
556 ! Check for end of layer card
557 !---------------------------------------------------------------------------
558 1 read(unit,'(A)') buffer
559
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if(trim(adjustl(buffer)).ne."END NETWORK_SETTINGS")then
560 write(0,*) trim(adjustl(buffer))
561 write(err_msg,'("END NETWORK_SETTINGS not where expected")')
562 call stop_program(err_msg)
563 return
564 end if
565
566 end subroutine read_network_settings
567 !-------------------------------------------------------------------------------
568 1 module subroutine read_optimiser_settings(this, unit)
569 !! Read the optimiser settings from a file
570 use coreutils, only: to_lower, to_upper, icount
571 use athena__optimiser, only: &
572 sgd_optimiser_type, adam_optimiser_type, rmsprop_optimiser_type, &
573 adagrad_optimiser_type, base_optimiser_type
574 implicit none
575
576 ! Arguments
577 class(network_type), intent(inout) :: this
578 !! Instance of network
579 integer, intent(in) :: unit
580 !! File unit
581
582 ! Local variables
583 integer :: stat
584 !! File status
585 character(20) :: optimiser_name
586 !! Name of the optimiser
587 character(256) :: buffer, err_msg, tmp
588 !! Buffer for reading lines, error message
589
590 ! Read until end of optimiser settings
591 1 read(unit,'(A)',iostat=stat) buffer
592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(stat.ne.0)then
593 write(err_msg,'("file encountered error (EoF?) before END ",A)') &
594 to_upper(this%name)
595 call stop_program(err_msg)
596 return
597 end if
598 1 read(buffer,*) tmp, optimiser_name
599
600 2 select case(trim(adjustl(to_lower(optimiser_name))))
601 case("sgd")
602 this%optimiser = sgd_optimiser_type()
603 case("adam")
604 this%optimiser = adam_optimiser_type()
605 case("rmsprop")
606 this%optimiser = rmsprop_optimiser_type()
607 case("adagrad")
608 this%optimiser = adagrad_optimiser_type()
609 case("","base")
610
8/22
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
1 this%optimiser = base_optimiser_type()
611 case default
612 write(err_msg,'("Unrecognised optimiser: ",A)') trim(adjustl(optimiser_name))
613 call stop_program(err_msg)
614
2/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
3 return
615 end select
616 1 call this%optimiser%read(unit)
617
618 end subroutine read_optimiser_settings
619 !###############################################################################
620
621
622 !###############################################################################
623 1 module subroutine build_from_onnx( &
624
4/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
1 this, nodes, initialisers, inputs, value_info, verbose &
625 )
626 !! Build network from ONNX nodes and initialisers
627 use coreutils, only: to_lower
628 implicit none
629
630 ! Arguments
631 class(network_type), intent(inout) :: this
632 !! Instance of network
633 type(onnx_node_type), dimension(:), intent(in) :: nodes
634 !! Array of ONNX nodes
635 type(onnx_initialiser_type), dimension(:), intent(in) :: initialisers
636 !! Array of ONNX initialisers
637 type(onnx_tensor_type), dimension(:), intent(in) :: inputs
638 !! Array of ONNX inputs
639 type(onnx_tensor_type), dimension(:), intent(in) :: value_info
640 !! Array of ONNX value infos
641 integer, optional, intent(in) :: verbose
642 !! Verbosity level
643
644 ! Local variables
645 integer :: i, j, k, j_out, layer_index
646 !! Loop indices
647 integer :: verbose_ = 0
648 !! Verbosity level
649 character(20) :: op_type
650 !! Lowercase op_type
651 character(64) :: tmp_name
652 !! Temporary name for matching
653 character(256) :: err_msg
654 !! Error message
655 1 integer, dimension(:), allocatable :: input_shape
656 !! Shape of input layer
657 1 integer, dimension(:), allocatable :: input_list
658 !! List of input layers
659 1 type(onnx_initialiser_type), dimension(:), allocatable :: init_list
660 !! List of initialisers for a specific node
661 1 type(onnx_tensor_type), dimension(:), allocatable :: value_info_list
662 !! List of value info tensors
663
664 1 verbose_ = 0
665
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(present(verbose)) verbose_ = verbose
666
667
668
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(.not.allocated(list_of_onnx_layer_creators))then
669 1 call allocate_list_of_onnx_layer_creators()
670 end if
671
672
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
2 do i = 1, size(inputs)
673
13/26
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 3 times.
✓ Branch 33 taken 1 times.
4 input_shape = inputs(i)%dims(2:size(inputs(i)%dims))
674
675 call this%add( &
676 input_layer_type(input_shape, index=i) &
677
6/48
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 42 taken 1 times.
✗ Branch 43 not taken.
✓ Branch 45 taken 1 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 1 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 50 not taken.
2 )
678 end do
679
680 ! Loop through nodes and create layers
681
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 9 taken 8 times.
✓ Branch 10 taken 1 times.
9 do i = 1, size(nodes)
682
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
8 if(verbose_.gt.0) write(*,*) "Processing ONNX node: ", trim(nodes(i)%name), &
683 " (", trim(nodes(i)%op_type), ")"
684
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
8 op_type = trim(adjustl(nodes(i)%op_type))
685
686 layer_index = &
687 findloc( &
688 [ list_of_onnx_layer_creators(:)%op_type ], &
689 op_type, &
690 dim = 1 &
691
10/16
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 8 times.
✓ Branch 11 taken 136 times.
✓ Branch 12 taken 8 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 8 times.
✓ Branch 15 taken 136 times.
✓ Branch 16 taken 8 times.
280 )
692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if(layer_index.eq.0)then
693 write(err_msg,'("unrecognised op_type ''",A)') trim(adjustl(nodes(i)%op_type))
694 call stop_program(err_msg)
695 return
696 end if
697
698 ! find all input layers and initialisers for this node
699 ! ... i.e. check over inputs for name matches
700 8 j_out = 0
701
8/24
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
8 allocate(init_list(0))
702
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
8 allocate(input_list(0))
703
8/22
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 8 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
8 allocate(value_info_list(0))
704
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 6 taken 14 times.
✓ Branch 7 taken 8 times.
22 do j = 1, size(nodes(i)%inputs)
705
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✓ Branch 9 taken 84 times.
✓ Branch 10 taken 14 times.
98 do k = 1, size(initialisers)
706
10/18
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 84 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 84 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 84 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 84 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 84 times.
✓ Branch 20 taken 84 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 84 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 6 times.
✓ Branch 25 taken 78 times.
98 if(trim(nodes(i)%inputs(j)) .eq. trim(initialisers(k)%name))then
707
33/60
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 6 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 6 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 6 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 6 times.
✓ Branch 25 taken 9 times.
✓ Branch 26 taken 6 times.
✓ Branch 27 taken 9 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 9 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 9 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 9 times.
✓ Branch 35 taken 6 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 6 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 6 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✓ Branch 45 taken 6 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 3 times.
✓ Branch 48 taken 6 times.
✓ Branch 49 taken 3 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 3 times.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✓ Branch 54 taken 3 times.
✓ Branch 55 taken 6 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 9 times.
✓ Branch 58 taken 6 times.
✓ Branch 59 taken 9 times.
✓ Branch 60 taken 6 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 9 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 9 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 9 times.
51 init_list = [ init_list, initialisers(k) ]
708 end if
709 end do
710
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✓ Branch 9 taken 14 times.
✓ Branch 10 taken 14 times.
28 do k = 1, size(inputs)
711
10/18
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 14 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 14 times.
✓ Branch 20 taken 14 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 14 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✓ Branch 25 taken 13 times.
28 if(trim(nodes(i)%inputs(j)) .eq. trim(inputs(k)%name))then
712
14/24
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✓ Branch 19 taken 1 times.
✓ Branch 20 taken 1 times.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✓ Branch 27 taken 1 times.
✓ Branch 28 taken 1 times.
3 input_list = [ input_list, k ]
713 end if
714 end do
715
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 14 times.
✓ Branch 13 taken 14 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 14 times.
✗ Branch 16 not taken.
14 tmp_name = trim(nodes(i)%inputs(j))
716
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 if(index(tmp_name, "_output").gt.0) &
717
4/8
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
✗ Branch 9 not taken.
7 tmp_name = trim(tmp_name(:index(tmp_name, "_output")-1))
718
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
✓ Branch 9 taken 112 times.
✓ Branch 10 taken 14 times.
134 do k = 1, size(nodes)
719
6/10
✗ Branch 1 not taken.
✓ Branch 2 taken 112 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 112 times.
✓ Branch 8 taken 112 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 112 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 7 times.
✓ Branch 13 taken 105 times.
126 if(trim(tmp_name) .eq. trim(nodes(k)%name))then
720
17/30
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 7 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 7 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 7 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 7 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 7 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 7 times.
✓ Branch 28 taken 7 times.
✓ Branch 29 taken 7 times.
✓ Branch 30 taken 7 times.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✓ Branch 33 taken 7 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 7 times.
✓ Branch 36 taken 7 times.
✓ Branch 37 taken 7 times.
21 input_list = [ input_list, k + size(inputs) ]
721 end if
722 end do
723 end do
724
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 8 times.
16 do j = 1, size(nodes(i)%outputs)
725
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
✓ Branch 9 taken 32 times.
✓ Branch 10 taken 8 times.
48 do k = 1, size(value_info)
726
10/18
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 32 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 32 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 32 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 32 times.
✓ Branch 20 taken 32 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 32 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 4 times.
✓ Branch 25 taken 28 times.
40 if(trim(nodes(i)%outputs(j)) .eq. trim(value_info(k)%name))then
727
26/54
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 4 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 4 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 4 times.
✓ Branch 25 taken 4 times.
✓ Branch 26 taken 4 times.
✓ Branch 27 taken 4 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 4 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 4 times.
✓ Branch 33 taken 4 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 4 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 4 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✓ Branch 43 taken 4 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 4 times.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 4 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 4 times.
✓ Branch 54 taken 4 times.
✓ Branch 55 taken 4 times.
✓ Branch 56 taken 4 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 4 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 4 times.
24 value_info_list = [ value_info_list, value_info(k) ]
728 end if
729 end do
730 end do
731
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
8 if(size(init_list)+size(input_list).ne.size(nodes(i)%inputs))then
732 if(verbose_.gt.0)then
733 write(0,*) "WARNING: not all inputs found for node ", &
734 trim(nodes(i)%name)
735 end if
736 end if
737
738 ! assume default operator
739
740 call this%add( &
741 list_of_onnx_layer_creators(layer_index)%create_ptr( &
742
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 nodes(i), init_list, value_info_list &
743 ), &
744 input_list = input_list &
745 ! operator = operator_in &
746
8/52
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 8 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✓ Branch 47 taken 8 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 8 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 8 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 8 times.
16 )
747
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 deallocate(input_list)
748
7/12
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 8 times.
22 deallocate(init_list)
749
6/10
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 8 times.
21 deallocate(value_info_list)
750 end do
751
752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(verbose_.gt.0) write(*,*) "ONNX model built with ", this%num_layers, " layers."
753
754
4/26
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
1 end subroutine build_from_onnx
755 !###############################################################################
756
757
758 !##############################################################################!
759 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
760 !##############################################################################!
761
762
763 !###############################################################################
764
8/12
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 130 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 53 times.
✓ Branch 7 taken 91 times.
✓ Branch 8 taken 53 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 53 times.
✗ Branch 11 not taken.
144 module subroutine add(this, layer, input_list, output_list, operator)
765 !! Add a layer to the network
766 implicit none
767
768 ! Arguments
769 class(network_type), intent(inout) :: this
770 !! Instance of network
771 class(base_layer_type), intent(in) :: layer
772 !! Layer to add to the network
773 integer, dimension(:), optional, intent(in) :: input_list
774 !! List of input layers
775 integer, dimension(:), optional, intent(in) :: output_list
776 !! List of output layers
777 class(*), optional, intent(in) :: operator
778 !! Operator to use to connect the layers
779
780 ! Local variables
781 integer :: i, vertex_index
782 !! Loop index
783 integer :: operator_
784 !! Operator to use to connect the layers
785 character(256) :: err_msg
786 !! Error message
787 integer, dimension(2) :: vertex_indices
788 !! Indices of the vertices to connect
789 144 type(container_layer_type), allocatable, dimension(:) :: model
790 !! Model to add the layer to
791
792
793
794
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 89 times.
144 if(.not.allocated(this%model))then
795
13/144
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 55 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 55 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 55 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 55 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 55 times.
✓ Branch 16 taken 55 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✓ Branch 89 taken 55 times.
✓ Branch 90 taken 55 times.
✗ Branch 91 not taken.
✓ Branch 92 taken 55 times.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 96 not taken.
✓ Branch 97 taken 55 times.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
275 this%model = [container_layer_type()]
796 55 this%num_layers = 1
797 else
798
16/30
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 89 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 89 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 89 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 89 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 89 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 89 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 89 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 89 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 89 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 89 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 89 times.
✓ Branch 31 taken 246 times.
✓ Branch 32 taken 89 times.
✓ Branch 33 taken 246 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 246 times.
335 allocate(model(size(this%model,dim=1)+1))
799
2/2
✓ Branch 0 taken 157 times.
✓ Branch 1 taken 89 times.
246 do i = 1, size(this%model,dim=1)
800
16/32
✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 157 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 157 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 157 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 157 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 157 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 157 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 157 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 157 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 157 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 157 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 157 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 157 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 157 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 157 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 157 times.
246 allocate(model(i)%layer, source=this%model(i)%layer)
801 end do
802
13/60
✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 157 times.
✓ Branch 3 taken 89 times.
✓ Branch 4 taken 157 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 157 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 157 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 157 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 157 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✓ Branch 52 taken 157 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 157 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 157 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 157 times.
✓ Branch 60 taken 89 times.
✗ Branch 61 not taken.
335 call move_alloc(model, this%model)
803 89 this%num_layers = this%num_layers + 1
804 end if
805
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 144 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 144 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 144 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 144 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 144 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 144 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 144 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 144 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 144 times.
144 allocate(this%model(size(this%model,dim=1))%layer, source=layer)
806
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 144 times.
144 this%model(size(this%model,dim=1))%layer%id = this%num_layers
807
808
809 144 operator_ = 1
810
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 138 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
144 if(present(operator))then
811 select type(operator)
812 type is(integer)
813 3 operator_ = operator
814 type is(character(*))
815 6 select case(trim(to_lower(operator)))
816 case("||", "concat", "concatenate", "append")
817 3 operator_ = 1
818 case("+", "add")
819 operator_ = 2
820 case("*", "x", "mul", "multiply")
821
2/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
9 operator_ = 3
822 end select
823 end select
824 end if
825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
144 if(operator_.gt.2.or.operator_.lt.1)then
826 call stop_program("invalid operator")
827 return
828 end if
829
830 ! edge_index(1) = index of the previous layer
831 ! abs(edge_index(2)) = index of the current layer
832 ! the -ve sign of edge_index(2) indicates that the edge goes from the
833 ! previous layer to the current layer
834 ! i.e. forward pass flows from positive to negative
835 ! adjacency(i,:) is all of the layers that i feeds forward to
836 ! adjacency(:,i) is all of the layers that feed forward to i
837 ! (i.e. the backward pass)
838 144 this%auto_graph%directed = .true.
839 call this%auto_graph%add_vertex( &
840 feature=[1._real32], id=this%num_layers, update_adjacency=.true. &
841 144 )
842
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 130 times.
144 if(present(input_list))then
843
6/10
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 14 times.
✓ Branch 11 taken 13 times.
✓ Branch 12 taken 14 times.
27 do i = 1, size(input_list), 1
844
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 13 times.
13 if(input_list(i).eq.0)then
845 vertex_index = 0
846 elseif( &
847
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 13 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 13 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 13 times.
13 input_list(i).le.-this%auto_graph%num_vertices .or. &
848 input_list(i).gt.this%auto_graph%num_vertices &
849 )then
850 write(err_msg, &
851 '("input vertex index ",I0," out of range (",I0,":",I0,")")' &
852 ) &
853 input_list(i), &
854 -this%auto_graph%num_vertices +1, &
855 this%auto_graph%num_vertices
856 call stop_program(err_msg)
857 return
858
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 13 times.
13 elseif(input_list(i).lt.0)then
859 vertex_index = this%auto_graph%num_vertices + input_list(i)
860 else
861 vertex_index = findloc( &
862 52 [this%auto_graph%vertex(:)%id], &
863
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
43 input_list(i), 1 &
864
11/18
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 13 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 13 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 13 times.
✓ Branch 15 taken 63 times.
✓ Branch 16 taken 13 times.
✓ Branch 17 taken 43 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 43 times.
✓ Branch 21 taken 13 times.
✓ Branch 22 taken 30 times.
119 )
865 end if
866
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 13 times.
39 vertex_indices = [ vertex_index, -this%auto_graph%num_vertices ]
867 call this%auto_graph%add_edge( &
868 index = vertex_indices, &
869 feature = [ 1._real32 ], &
870 id = operator_, &
871 update_adjacency = .true. &
872 27 )
873 end do
874
3/4
✓ Branch 1 taken 130 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 26 times.
✓ Branch 4 taken 104 times.
130 elseif(trim(layer%type).ne."inpt".and.this%auto_graph%num_vertices.gt.1)then
875 vertex_indices = [ &
876 this%auto_graph%num_vertices - 1, &
877 -this%auto_graph%num_vertices &
878
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 26 times.
78 ]
879 call this%auto_graph%add_edge( &
880 index = vertex_indices, &
881 feature = [ 1._real32 ], &
882 id = operator_, &
883 update_adjacency = .true. &
884 26 )
885 end if
886
887
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 91 times.
144 if(present(output_list))then
888
6/10
✓ Branch 0 taken 53 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 53 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 53 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 53 times.
✓ Branch 11 taken 53 times.
✓ Branch 12 taken 53 times.
106 do i = 1, size(output_list), 1
889 vertex_index = findloc( &
890 212 [this%auto_graph%vertex(:)%id], &
891
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 output_list(i), 1 &
892
11/18
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 53 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 53 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 53 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 53 times.
✓ Branch 15 taken 133 times.
✓ Branch 16 taken 53 times.
✓ Branch 17 taken 57 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 57 times.
✓ Branch 21 taken 53 times.
✓ Branch 22 taken 4 times.
243 )
893
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 53 times.
159 vertex_indices = [ this%auto_graph%num_vertices, -vertex_index ]
894 call this%auto_graph%add_edge( &
895 index = vertex_indices, &
896 feature = [ 1._real32 ], &
897 id = operator_, &
898 update_adjacency = .true. &
899 106 )
900 end do
901 end if
902
903
1/60
✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
144 end subroutine add
904 !###############################################################################
905
906
907 !###############################################################################
908 module function network_setup( &
909 layers, optimiser, loss_method, accuracy_method, &
910 metrics, batch_size &
911 ) result(network)
912 !! Setup the network
913 implicit none
914
915 ! Arguments
916 type(container_layer_type), dimension(:), intent(in) :: layers
917 !! Layers to add to the network
918 class(base_optimiser_type), optional, intent(in) :: optimiser
919 !! Optimiser to use for training
920 class(*), optional, intent(in) :: loss_method
921 !! Loss method
922 character(*), optional, intent(in) :: accuracy_method
923 !! Accuracy method
924 class(*), dimension(..), optional, intent(in) :: metrics
925 !! Metrics
926 integer, optional, intent(in) :: batch_size
927 !! Batch size
928
929 type(network_type) :: network
930 !! Network to setup
931
932 ! Local variables
933 integer :: l
934 !! Loop index
935
936
937 !---------------------------------------------------------------------------
938 ! Handle optional arguments
939 !---------------------------------------------------------------------------
940 if(present(loss_method)) call network%set_loss(loss_method)
941 if(present(accuracy_method)) call network%set_accuracy(accuracy_method)
942 if(present(metrics)) call network%set_metrics(metrics)
943 if(present(batch_size)) network%batch_size = batch_size
944 network%auto_graph%directed = .true.
945
946
947 !---------------------------------------------------------------------------
948 ! Add layers to network
949 !---------------------------------------------------------------------------
950 do l = 1, size(layers)
951 call network%add(layers(l)%layer)
952 end do
953
954
955 !---------------------------------------------------------------------------
956 ! Compile network if optimiser present
957 !---------------------------------------------------------------------------
958 if(present(optimiser)) call network%compile(optimiser)
959
960 end function network_setup
961 !###############################################################################
962
963
964 !###############################################################################
965 51 module subroutine set_metrics(this, metrics)
966 !! Set the metrics for the network
967 use coreutils, only: to_lower
968 implicit none
969
970 ! Arguments
971 class(network_type), intent(inout) :: this
972 !! Instance of network
973 class(*), dimension(..), intent(in) :: metrics
974 !! Metrics
975
976 ! Local variables
977 integer :: i
978 !! Loop index
979
980
981
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 51 times.
153 this%metrics%active = .false.
982 51 this%metrics(1)%key = "loss"
983 51 this%metrics(2)%key = "accuracy"
984
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 51 times.
153 this%metrics%threshold = 1.E-1_real32
985 select rank(metrics)
986 #if defined(GFORTRAN)
987 rank(0)
988 select type(metrics)
989 type is(character(*))
990 ! ERROR: ifort cannot identify that the rank of metrics has been ...
991 ! ... identified as scalar here
992 where(to_lower(trim(metrics)).eq.this%metrics%key)
993 this%metrics%active = .true.
994 end where
995 end select
996 #endif
997 rank(1)
998
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 select type(metrics)
999 type is(character(*))
1000
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 50 times.
100 do i=1,size(metrics,1)
1001
7/10
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
✓ Branch 8 taken 50 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 100 times.
✓ Branch 11 taken 50 times.
✓ Branch 12 taken 50 times.
✓ Branch 13 taken 50 times.
200 where(to_lower(trim(metrics(i))).eq.this%metrics%key)
1002 this%metrics%active = .true.
1003 end where
1004 end do
1005 type is(metric_dict_type)
1006
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(size(metrics,1).eq.2)then
1007
12/20
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✓ Branch 15 taken 2 times.
✓ Branch 16 taken 1 times.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✓ Branch 20 taken 1 times.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 2 times.
✗ Branch 24 not taken.
3 this%metrics(:2) = metrics(:2)
1008 else
1009 call stop_program("invalid length array for metric_dict_type")
1010 return
1011 end if
1012 end select
1013 rank default
1014 call stop_program("provided metrics rank in compile invalid")
1015 return
1016 end select
1017
1018 end subroutine set_metrics
1019 !###############################################################################
1020
1021
1022 !###############################################################################
1023 60 module subroutine set_loss(this, loss_method, verbose)
1024 !! Set the loss method for the network
1025 use coreutils, only: to_lower
1026 use athena__loss, only: &
1027 bce_loss_type, &
1028 cce_loss_type, &
1029 mae_loss_type, &
1030 mse_loss_type, &
1031 nll_loss_type, &
1032 huber_loss_type
1033 implicit none
1034
1035 ! Arguments
1036 class(network_type), intent(inout) :: this
1037 !! Instance of network
1038 class(*), intent(in) :: loss_method
1039 !! Loss method
1040 integer, optional, intent(in) :: verbose
1041 !! Verbosity level
1042
1043 ! Local variables
1044 integer :: verbose_
1045 !! Verbosity level
1046 60 character(len=:), allocatable :: loss_method_
1047 !! Loss method
1048 character(256) :: err_msg
1049 !! Error message
1050
1051
1052
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 7 times.
60 if(present(verbose))then
1053 53 verbose_ = verbose
1054 else
1055 7 verbose_ = 0
1056 end if
1057
1058 !---------------------------------------------------------------------------
1059 ! Handle analogous definitions
1060 !---------------------------------------------------------------------------
1061
1062 !---------------------------------------------------------------------------
1063 ! Set loss method
1064 !---------------------------------------------------------------------------
1065 select type(loss_method)
1066 class is(base_loss_type)
1067 this%loss = loss_method
1068 if(verbose_.gt.0) write(*,*) "Loss method: ", trim(loss_method%name)
1069 loss_method_ = trim(loss_method%name)
1070 type is(character(*))
1071
3/8
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 60 times.
60 loss_method_ = to_lower(loss_method)
1072 1 select case(loss_method)
1073 case("binary_crossentropy")
1074
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 loss_method_ = "bce"
1075 case("categorical_crossentropy")
1076
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 loss_method_ = "cce"
1077 case("mean_absolute_error")
1078
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 loss_method_ = "mae"
1079 case("mean_squared_error")
1080
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 loss_method_ = "mse"
1081 case("negative_log_likelihood")
1082
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 loss_method_ = "nll"
1083 case("huber")
1084
11/15
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 54 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
60 loss_method_ = "hub"
1085 end select
1086 60 select case(loss_method_)
1087 case("bce")
1088
5/12
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 this%loss = bce_loss_type()
1089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(verbose_.gt.0) write(*,*) "Loss method: Binary Cross Entropy"
1090 case("cce")
1091
5/12
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 this%loss = cce_loss_type()
1092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(verbose_.gt.0) write(*,*) "Loss method: Categorical Cross Entropy"
1093 case("mae")
1094
5/12
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 this%loss = mae_loss_type()
1095
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(verbose_.gt.0) write(*,*) "Loss method: Mean Absolute Error"
1096 case("mse")
1097
8/12
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 54 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 54 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 54 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 55 times.
✗ Branch 14 not taken.
56 this%loss = mse_loss_type()
1098
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 43 times.
67 if(verbose_.gt.0) write(*,*) "Loss method: Mean Squared Error"
1099 case("nll")
1100
5/12
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 this%loss = nll_loss_type()
1101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(verbose_.gt.0) write(*,*) "Loss method: Negative Log Likelihood"
1102 case("hub")
1103
5/12
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
2 this%loss = huber_loss_type()
1104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(verbose_.gt.0) write(*,*) "Loss method: Huber"
1105 case default
1106 write(err_msg,'(A)') &
1107 "No loss method provided" // &
1108 achar(13) // achar(10) // &
1109 "Failed loss method: "//trim(loss_method_)
1110 call stop_program(trim(err_msg))
1111
6/7
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 55 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
60 return
1112 end select
1113 end select
1114
6/8
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 60 times.
60 this%loss_method = loss_method_
1115
1116
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 end subroutine set_loss
1117 !###############################################################################
1118
1119
1120 !###############################################################################
1121 19 module subroutine set_accuracy(this, accuracy_method, verbose)
1122 !! Set the accuracy method for the network
1123 use coreutils, only: to_lower
1124 use athena__accuracy, only: &
1125 categorical_score, &
1126 mae_score, &
1127 mse_score, &
1128 rmse_score, &
1129 r2_score
1130 implicit none
1131
1132 ! Arguments
1133 class(network_type), intent(inout) :: this
1134 !! Instance of network
1135 character(*), intent(in) :: accuracy_method
1136 !! Accuracy method
1137 integer, optional, intent(in) :: verbose
1138 !! Verbosity level
1139
1140 ! Local variables
1141 integer :: verbose_
1142 !! Verbosity level
1143 19 character(len=:), allocatable :: accuracy_method_
1144 !! Accuracy method
1145 character(256) :: err_msg
1146 !! Error message
1147
1148
1149 19 if(present(verbose))then
1150 13 verbose_ = verbose
1151 else
1152 6 verbose_ = 0
1153 end if
1154
1155 !---------------------------------------------------------------------------
1156 ! Handle analogous definitions
1157 !---------------------------------------------------------------------------
1158
3/8
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 19 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 19 times.
19 accuracy_method_ = to_lower(accuracy_method)
1159 1 select case(accuracy_method)
1160 case("categorical")
1161
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 accuracy_method_ = "cat"
1162 case("mean_absolute_error")
1163
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 accuracy_method_ = "mae"
1164 case("mean_squared_error")
1165
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 accuracy_method_ = "mse"
1166 case("root_mean_squared_error")
1167
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
1 accuracy_method_ = "rmse"
1168 case("r2", "r^2", "r squared")
1169
11/14
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
19 accuracy_method_ = "r2"
1170 end select
1171
1172 !---------------------------------------------------------------------------
1173 ! Set accuracy method
1174 !---------------------------------------------------------------------------
1175 1 select case(accuracy_method_)
1176 case("cat")
1177 1 this%get_accuracy => categorical_score
1178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(verbose_.gt.0) write(*,*) "Accuracy method: Categorical "
1179 case("mae")
1180 1 this%get_accuracy => mae_score
1181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(verbose_.gt.0) write(*,*) "Accuracy method: Mean Absolute Error"
1182 case("mse")
1183 14 this%get_accuracy => mse_score
1184
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
16 if(verbose_.gt.0) write(*,*) "Accuracy method: Mean Squared Error"
1185 case("rmse")
1186 1 this%get_accuracy => rmse_score
1187
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(verbose_.gt.0) write(*,*) "Accuracy method: Root Mean Squared Error"
1188 case("r2")
1189 2 this%get_accuracy => r2_score
1190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(verbose_.gt.0) write(*,*) "Accuracy method: R^2"
1191 case default
1192 write(err_msg,'(A)') &
1193 "No accuracy method provided" // &
1194 achar(13) // achar(10) // &
1195 "Failed accuracy method: "//trim(accuracy_method_)
1196 call stop_program(trim(err_msg))
1197
5/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
19 return
1198 end select
1199
6/8
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 19 times.
19 this%accuracy_method = accuracy_method_
1200
1201
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
38 end subroutine set_accuracy
1202 !###############################################################################
1203
1204
1205 !###############################################################################
1206 11 module subroutine reset(this)
1207 !! Reset the network
1208 implicit none
1209
1210 ! Arguments
1211 class(network_type), intent(inout) :: this
1212 !! Instance of network
1213
1214 11 this%epoch = 0
1215 11 this%accuracy_val = 0._real32
1216 11 this%loss_val = huge(1._real32)
1217 11 this%batch_size = 0
1218 11 this%num_layers = 0
1219 11 this%num_outputs = 0
1220
4/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
20 if(allocated(this%optimiser)) deallocate(this%optimiser)
1221
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
22 call this%set_metrics(["loss"])
1222
15/62
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 31 times.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 31 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 31 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 31 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 31 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 31 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✓ Branch 54 taken 31 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 31 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 31 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 31 times.
✗ Branch 62 not taken.
✓ Branch 63 taken 10 times.
52 if(allocated(this%model)) deallocate(this%model)
1223
4/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
20 if(allocated(this%loss)) deallocate(this%loss)
1224 11 this%get_accuracy => null()
1225
1226
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
11 if(allocated(this%vertex_order)) deallocate(this%vertex_order)
1227
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
11 if(allocated(this%leaf_vertices)) deallocate(this%leaf_vertices)
1228
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
11 if(allocated(this%root_vertices)) deallocate(this%root_vertices)
1229
21/32
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 11 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 11 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11 times.
✓ Branch 17 taken 10 times.
✓ Branch 18 taken 1 times.
✓ Branch 19 taken 10 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 31 times.
✓ Branch 22 taken 10 times.
✓ Branch 23 taken 31 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 10 times.
✓ Branch 26 taken 1 times.
✓ Branch 27 taken 10 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 21 times.
✓ Branch 30 taken 10 times.
✓ Branch 31 taken 21 times.
✗ Branch 32 not taken.
83 this%auto_graph = graph_type(directed=.true.)
1230
1231 11 end subroutine reset
1232 !###############################################################################
1233
1234
1235 !###############################################################################
1236 54 module subroutine compile( &
1237 this, optimiser, loss_method, accuracy_method, &
1238 metrics, batch_size, verbose &
1239 )
1240 !! Compile the network
1241 implicit none
1242
1243 ! Arguments
1244 class(network_type), intent(inout) :: this
1245 !! Instance of network
1246 class(base_optimiser_type), optional, intent(in) :: optimiser
1247 !! Optimiser to use for training
1248 class(*), optional, intent(in) :: loss_method
1249 !! Loss method
1250 character(*), optional, intent(in) :: accuracy_method
1251 !! Accuracy method
1252 class(*), dimension(..), optional, intent(in) :: metrics
1253 !! Metrics
1254 integer, optional, intent(in) :: batch_size
1255 !! Batch size
1256 integer, optional, intent(in) :: verbose
1257 !! Verbosity level
1258
1259 ! Local variables
1260 integer :: i, j, k, child_id, parent_id, layer_id, num_inputs, input_rank
1261 !! Loop index
1262 integer :: parent_vertex, vertex_idx
1263 !! Vertex indices
1264 integer :: layer_rank, parent_rank, operator
1265 !! Ranks of layers
1266 integer :: verbose_ = 0
1267 !! Verbosity level
1268 logical :: use_graph_input = .false.
1269 !! Boolean whether to use graph input
1270 logical :: l_flatten_child, l_set_input_shape
1271 !! Booleans whether to flatten child or set input shape
1272 54 integer, dimension(:), allocatable :: input_shape, &
1273 54 child_vertices, parent_vertices, output_ranks, parent_ids
1274 !! Shapes of the input and output of the layers
1275 54 integer, dimension(:,:), allocatable :: merge_shape
1276 !! Shapes of the inputs to merge layers
1277 class(base_layer_type), allocatable :: &
1278 216 t_input_layer, t_flatten_layer, t_merge_layer
1279 !! Temporary input, flatten, and merge layers
1280
1281
1282 !---------------------------------------------------------------------------
1283 ! Initialise optional arguments
1284 !---------------------------------------------------------------------------
1285 50 if(present(verbose)) verbose_ = verbose
1286
1287
1288 !---------------------------------------------------------------------------
1289 ! Initialise metrics
1290 !---------------------------------------------------------------------------
1291
3/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 39 times.
✗ Branch 3 not taken.
54 if(present(metrics)) call this%set_metrics(metrics)
1292
1293
1294 !---------------------------------------------------------------------------
1295 ! Initialise loss and accuracy methods
1296 !---------------------------------------------------------------------------
1297
3/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 53 times.
✗ Branch 3 not taken.
54 if(present(loss_method)) call this%set_loss(loss_method, verbose_)
1298
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 41 times.
54 if(present(accuracy_method)) &
1299 13 call this%set_accuracy(accuracy_method, verbose_)
1300
1301
1302 !---------------------------------------------------------------------------
1303 ! Check for input layers at root vertices
1304 !---------------------------------------------------------------------------
1305 54 this%auto_graph%directed = .true.
1306 54 call this%build_root_vertices()
1307
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 54 times.
108 do i = 1, size(this%root_vertices)
1308
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 54 times.
54 layer_id = this%auto_graph%vertex(this%root_vertices(i))%id
1309
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
54 if(.not.allocated(this%model(layer_id)%layer%input_shape))then
1310 call stop_program("input_shape of first layer not defined")
1311 return
1312 end if
1313 54 use_graph_input = .false.
1314 108 select type( root => this%model(layer_id)%layer)
1315 class is(input_layer_type)
1316 4 cycle
1317 class is(learnable_layer_type)
1318
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 50 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 50 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 50 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 50 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 50 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 50 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 76 times.
✓ Branch 23 taken 50 times.
126 input_shape = root%input_shape
1319
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
100 use_graph_input = root%use_graph_input
1320 class default
1321 input_shape = root%input_shape
1322 end select
1323 t_input_layer = input_layer_type(&
1324 input_shape = input_shape, &
1325 index = i, &
1326 use_graph_input = use_graph_input, &
1327 verbose=verbose_ &
1328
9/58
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 50 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 50 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 14 taken 50 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 50 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✓ Branch 54 taken 50 times.
✗ Branch 55 not taken.
✓ Branch 57 taken 50 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 50 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 50 times.
✗ Branch 62 not taken.
50 )
1329 call this%add( &
1330 100 t_input_layer, output_list = [ this%model(layer_id)%layer%id ] &
1331
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
✓ Branch 6 taken 50 times.
✓ Branch 7 taken 50 times.
100 )
1332 ! NEED TO CALL layer%init?
1333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 deallocate(input_shape)
1334
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✓ Branch 3 taken 50 times.
✗ Branch 4 not taken.
50 deallocate(t_input_layer)
1335
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
50 this%root_vertices(i) = this%num_layers
1336
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
104 if(i.eq.1)then
1337
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 50 times.
119 do j = 1, this%auto_graph%num_edges
1338
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 69 times.
69 if(this%auto_graph%edge(j)%index(1).eq.0) &
1339
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
50 this%auto_graph%edge(j)%index(1) = this%num_layers
1340 end do
1341 end if
1342 end do
1343 54 call this%auto_graph%generate_adjacency()
1344
1345
1346 !---------------------------------------------------------------------------
1347 ! Identify whether input is graph type
1348 !---------------------------------------------------------------------------
1349
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✓ Branch 6 taken 13 times.
✓ Branch 7 taken 41 times.
54 if( &
1350 this%model( &
1351
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 54 times.
54 this%auto_graph%vertex(this%root_vertices(1))%id &
1352 )%layer%use_graph_input &
1353 )then
1354 13 this%use_graph_input = .true.
1355 else
1356 41 this%use_graph_input = .false.
1357 end if
1358
1359
1360 !---------------------------------------------------------------------------
1361 ! Check for zero input rank layers
1362 !---------------------------------------------------------------------------
1363
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 54 times.
191 do i = 1, size(this%auto_graph%vertex, dim = 1)
1364
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 137 times.
137 layer_id = this%auto_graph%vertex(i)%id
1365
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 137 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 133 times.
191 if(this%model(layer_id)%layer%input_rank.eq.0)then
1366 parent_ids = pack( &
1367 72 [ ( &
1368 this%auto_graph%vertex(j)%id, &
1369 24 j = 1, size(this%auto_graph%adjacency(:,i)) &
1370 ) ], &
1371 24 this%auto_graph%adjacency(:,i) .ne. 0 &
1372
27/44
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 4 times.
✓ Branch 21 taken 36 times.
✓ Branch 22 taken 4 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 36 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 36 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 4 times.
✓ Branch 31 taken 36 times.
✓ Branch 32 taken 4 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 4 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 4 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 4 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 4 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 4 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 4 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 4 times.
✓ Branch 53 taken 36 times.
✓ Branch 54 taken 4 times.
✓ Branch 56 taken 3 times.
✓ Branch 57 taken 1 times.
✓ Branch 58 taken 1 times.
✓ Branch 59 taken 3 times.
112 )
1373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(size(parent_ids).eq.0) cycle
1374 output_ranks = [ ( this%model(parent_ids(j))%layer%output_rank, &
1375
18/26
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 4 times.
✓ Branch 19 taken 4 times.
✓ Branch 20 taken 4 times.
✓ Branch 21 taken 3 times.
✓ Branch 22 taken 1 times.
✓ Branch 23 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 4 times.
✓ Branch 28 taken 4 times.
16 j=1,size(parent_ids) ) ]
1376
10/18
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✓ Branch 18 taken 4 times.
✓ Branch 19 taken 4 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 4 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 4 times.
8 if(any(output_ranks.ne.output_ranks(1)))then
1377 write(0,*) output_ranks
1378 call stop_program( &
1379 "input rank of layer "//trim(this%model(layer_id)%layer%name) // &
1380 " is zero, but multiple parents with different output ranks" &
1381 )
1382 return
1383 end if
1384
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
4 input_rank = this%model(parent_ids(1))%layer%output_rank
1385 8 call this%model(layer_id)%layer%set_rank( &
1386 input_rank = input_rank, &
1387 output_rank = input_rank &
1388
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
4 )
1389 end if
1390 end do
1391
1392
1393 !---------------------------------------------------------------------------
1394 ! Check for required flatten layers
1395 !---------------------------------------------------------------------------
1396 54 i = 0
1397 140 flatten_loop: do
1398 194 i = i + 1
1399
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 140 times.
194 if(i.gt.this%auto_graph%num_vertices) exit flatten_loop
1400
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
140 layer_id = this%auto_graph%vertex(i)%id
1401
1402 ! get all child vertices
1403 child_vertices = pack( &
1404 840 [(j, j=1,size(this%auto_graph%adjacency(i,:)))], &
1405 840 this%auto_graph%adjacency(i,:) .ne. 0 &
1406
23/40
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 140 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 140 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 140 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 140 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 140 times.
✓ Branch 21 taken 438 times.
✓ Branch 22 taken 140 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 140 times.
✓ Branch 25 taken 438 times.
✓ Branch 26 taken 140 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 140 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 140 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 140 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 140 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 140 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 140 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 140 times.
✓ Branch 47 taken 438 times.
✓ Branch 48 taken 140 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 140 times.
✓ Branch 52 taken 140 times.
✗ Branch 53 not taken.
1454 )
1407
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 137 times.
223 child_loop: do j = 1, size(child_vertices)
1408 ! Get layer ID (needed for add() function's output_list parameter)
1409
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 86 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 86 times.
86 child_id = this%auto_graph%vertex(child_vertices(j))%id
1410
5/8
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
✓ Branch 7 taken 86 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 82 times.
86 if(trim(this%model(layer_id)%layer%type).eq."flat") cycle child_loop
1411
6/10
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 82 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 82 times.
✓ Branch 12 taken 79 times.
✓ Branch 13 taken 3 times.
82 if( this%model(layer_id)%layer%output_rank .eq. &
1412 79 this%model(child_id)%layer%input_rank ) cycle child_loop
1413
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
3 if(this%model(layer_id)%layer%output_rank.eq.0) cycle child_loop
1414
1415 ! get all parent vertices of the child vertex
1416 parent_vertices = pack( &
1417 [(k, k=1,size(this%auto_graph%adjacency(:,child_vertices(j))))], &
1418 this%auto_graph%adjacency(:,child_vertices(j)) .ne. 0 &
1419
27/48
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 3 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 3 times.
✓ Branch 25 taken 11 times.
✓ Branch 26 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✓ Branch 29 taken 11 times.
✓ Branch 30 taken 3 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 3 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 3 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 3 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 3 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 3 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 3 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 3 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 3 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 3 times.
✓ Branch 55 taken 11 times.
✓ Branch 56 taken 3 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 3 times.
✓ Branch 60 taken 3 times.
✗ Branch 61 not taken.
36 )
1420 3 l_flatten_child = .true.
1421
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 do k = 1, size(parent_vertices)
1422
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 parent_id = this%auto_graph%vertex(parent_vertices(k))%id
1423 !check if ranks match, rather than input and output shapes
1424
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
3 if( this%model(layer_id)%layer%output_rank .ne. &
1425 this%model(parent_id)%layer%input_rank &
1426 3 ) l_flatten_child = .false.
1427 end do
1428 t_flatten_layer = flatten_layer_type( &
1429 6 input_rank = this%model(layer_id)%layer%output_rank &
1430
11/62
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 20 taken 3 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 3 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✓ Branch 61 taken 3 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 3 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 3 times.
✗ Branch 67 not taken.
✓ Branch 68 taken 3 times.
3 )
1431
1432
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if(l_flatten_child)then
1433 ! add flatten layer in the place of the child layer
1434 6 operator = this%auto_graph%edge( &
1435 this%auto_graph%adjacency(parent_vertices(1),child_vertices(j)) &
1436
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 3 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 3 times.
3 )%id
1437 call this%auto_graph%remove_edges( &
1438 indices = [ &
1439 12 this%auto_graph%adjacency( &
1440 parent_vertices(:),child_vertices(j) &
1441 ) &
1442 ] &
1443
12/20
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✓ Branch 13 taken 3 times.
✓ Branch 14 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✓ Branch 23 taken 3 times.
✓ Branch 24 taken 3 times.
9 )
1444 call this%add( &
1445 t_flatten_layer, &
1446 input_list=[parent_vertices(:)], output_list=[child_id], &
1447 operator=operator &
1448
12/18
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✓ Branch 11 taken 3 times.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 3 times.
✓ Branch 17 taken 3 times.
✓ Branch 18 taken 3 times.
12 )
1449 else
1450 ! add flatten layer between the current layer and the child layer
1451 operator = this%auto_graph%edge( &
1452 this%auto_graph%adjacency(i,child_vertices(j)) &
1453 )%id
1454 call this%auto_graph%remove_edges( &
1455 indices = [this%auto_graph%adjacency(i,child_vertices(j))] &
1456 )
1457 call this%add( &
1458 t_flatten_layer, input_list = [layer_id], &
1459 output_list = [child_id], &
1460 operator=operator &
1461 )
1462 end if
1463
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
3 deallocate(t_flatten_layer)
1464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 deallocate(child_vertices)
1465 140 cycle flatten_loop
1466 end do child_loop
1467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 137 times.
137 deallocate(child_vertices)
1468 end do flatten_loop
1469 54 call this%build_vertex_order()
1470
1471
1472 !---------------------------------------------------------------------------
1473 ! Check for required merge layers
1474 !---------------------------------------------------------------------------
1475 54 i = 0
1476 140 merge_loop: do
1477 194 i = i + 1
1478
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 140 times.
194 if(i.gt.this%auto_graph%num_vertices) exit merge_loop
1479
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
140 layer_id = this%auto_graph%vertex(i)%id
1480
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 140 times.
140 if(this%model(layer_id)%layer%type.eq."merg") cycle merge_loop
1481
1482 ! get all child vertices
1483 parent_vertices = pack( &
1484 840 [(j, j=1,size(this%auto_graph%adjacency(:,i)))], &
1485 840 this%auto_graph%adjacency(:,i) .ne. 0 &
1486
25/40
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 140 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 140 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 140 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 140 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 140 times.
✓ Branch 21 taken 442 times.
✓ Branch 22 taken 140 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 140 times.
✓ Branch 25 taken 442 times.
✓ Branch 26 taken 140 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 140 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 140 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 140 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 140 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 140 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 140 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 140 times.
✓ Branch 47 taken 442 times.
✓ Branch 48 taken 140 times.
✓ Branch 50 taken 89 times.
✓ Branch 51 taken 51 times.
✓ Branch 52 taken 108 times.
✓ Branch 53 taken 32 times.
1466 )
1487
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 if(size(parent_vertices).le.1) cycle merge_loop
1488
1489 ! get edge id for merge layer
1490 operator = this%auto_graph%edge( &
1491 this%auto_graph%adjacency(parent_vertices(1),i) &
1492 )%id
1493
1494 ! remove edges from parents to this layer
1495 do j = 1, size(parent_vertices)
1496 call this%auto_graph%remove_edges( &
1497 indices = [this%auto_graph%adjacency(parent_vertices(j),i)] &
1498 )
1499 end do
1500 parent_ids = &
1501 [ ( &
1502 this%auto_graph%vertex(parent_vertices(k))%id, &
1503 k = 1, size(parent_vertices) &
1504 ) ]
1505 select case(operator)
1506 case(1) ! concatenate
1507 t_merge_layer = concat_layer_type( &
1508 input_layer_ids = parent_ids, &
1509 input_rank = this%model(layer_id)%layer%input_rank &
1510 )
1511 case(2) ! add
1512 t_merge_layer = add_layer_type( &
1513 input_layer_ids = parent_ids, &
1514 input_rank = this%model(layer_id)%layer%input_rank &
1515 )
1516 ! case(3) ! multiply
1517 ! t_merge_layer = multiply_layer_type( &
1518 ! input_layer_ids = parent_vertices &
1519 ! )
1520 case default
1521 write(0,*) "invalid merge operator: ", operator
1522 call stop_program("invalid merge operator")
1523 return
1524 end select
1525 t_merge_layer%use_graph_input = this%model(layer_id)%layer%use_graph_input
1526 t_merge_layer%use_graph_output = t_merge_layer%use_graph_input
1527 call this%add( &
1528 t_merge_layer, &
1529 input_list = parent_ids, &
1530 output_list = [layer_id] &
1531 )
1532 deallocate(t_merge_layer)
1533 end do merge_loop
1534 54 call this%build_vertex_order()
1535
1536
1537 ! Update number of layers
1538 !---------------------------------------------------------------------------
1539 54 this%num_layers = size(this%model,dim=1)
1540
1541
1542
1543 !---------------------------------------------------------------------------
1544 ! Initialise layers
1545 !---------------------------------------------------------------------------
1546
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 54 times.
194 do i = 1, size(this%vertex_order, dim = 1)
1547
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
140 vertex_idx = this%vertex_order(i)
1548
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
140 layer_id = this%auto_graph%vertex(vertex_idx)%id
1549
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
✓ Branch 6 taken 112 times.
✓ Branch 7 taken 28 times.
140 if(allocated(this%model(layer_id)%layer%input_shape))then
1550 112 l_set_input_shape = .false.
1551 else
1552 28 l_set_input_shape = .true.
1553 end if
1554
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 112 times.
140 if(l_set_input_shape)then
1555
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
28 layer_rank = this%model(layer_id)%layer%input_rank
1556 28 parent_rank = 0
1557
1558 56 select type( layer => this%model(layer_id)%layer )
1559 class is(merge_layer_type)
1560 ! loop over all parent layers
1561 allocate( &
1562 merge_shape( &
1563 this%model(layer_id)%layer%input_rank, &
1564 size(layer%input_layer_ids) &
1565 ) &
1566 )
1567 do k = 1, size(layer%input_layer_ids)
1568 merge_shape(:,k) = &
1569 this%model(layer%input_layer_ids(k))%layer%output_shape
1570 end do
1571 input_shape = layer%calc_input_shape(merge_shape)
1572 deallocate(merge_shape)
1573 class default
1574
1575 allocate( &
1576 input_shape(this%model(layer_id)%layer%input_rank), &
1577 source = 0 &
1578
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 28 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 28 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 28 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 28 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 28 times.
28 )
1579
2/2
✓ Branch 0 taken 150 times.
✓ Branch 1 taken 28 times.
178 do j = 1, this%auto_graph%num_vertices
1580
6/10
✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 150 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 150 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 150 times.
✓ Branch 12 taken 122 times.
✓ Branch 13 taken 28 times.
150 if(this%auto_graph%adjacency(j,vertex_idx).eq.0) cycle
1581
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
28 parent_id = this%auto_graph%vertex(j)%id
1582
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
28 parent_rank = this%model(parent_id)%layer%output_rank
1583
1584
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 1 times.
56 if(layer_rank .eq. parent_rank)then
1585 input_shape(:) = input_shape(:) + &
1586
18/34
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 27 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 27 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 27 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 27 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 27 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 27 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 27 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 27 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 27 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 27 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 27 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 27 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 27 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 27 times.
✓ Branch 40 taken 50 times.
✓ Branch 41 taken 27 times.
77 this%model(parent_id)%layer%output_shape
1587
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 elseif(layer_rank .eq. 1)then
1588 input_shape(1) = input_shape(1) + &
1589
12/22
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✓ Branch 22 taken 1 times.
✓ Branch 23 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1 times.
2 product( this%model(parent_id)%layer%output_shape )
1590 end if
1591 end do
1592 end select
1593 56 call this%model(layer_id)%layer%init( &
1594 input_shape = input_shape, &
1595 verbose = verbose_ &
1596
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
28 )
1597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 deallocate(input_shape)
1598 end if
1599
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 102 times.
194 if(verbose_.gt.0)then
1600
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 38 times.
38 write(*,*) "layer: ", layer_id, this%model(layer_id)%layer%type
1601
8/14
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 38 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 38 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 38 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 38 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 38 times.
✓ Branch 19 taken 77 times.
✓ Branch 20 taken 38 times.
115 write(*,*) this%model(layer_id)%layer%input_shape
1602
8/14
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 38 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 38 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 38 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 38 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 38 times.
✓ Branch 19 taken 71 times.
✓ Branch 20 taken 38 times.
109 write(*,*) this%model(layer_id)%layer%output_shape
1603 end if
1604 end do
1605
1606
1607 ! Set number of outputs
1608 !---------------------------------------------------------------------------
1609 54 this%num_outputs = 0
1610 54 call this%build_leaf_vertices()
1611
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 54 times.
108 do i = 1, size(this%leaf_vertices,1)
1612 this%num_outputs = this%num_outputs + &
1613 product( &
1614 324 this%model( &
1615 216 this%auto_graph%vertex(this%leaf_vertices(i))%id &
1616 )%layer%output_shape &
1617
12/22
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 54 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 54 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 54 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 54 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 54 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 54 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 54 times.
✓ Branch 30 taken 69 times.
✓ Branch 31 taken 54 times.
177 )
1618 end do
1619
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 45 times.
54 if( &
1620 this%model( &
1621
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 54 times.
54 this%auto_graph%vertex(this%leaf_vertices(1))%id &
1622 )%layer%use_graph_output &
1623 )then
1624 9 this%use_graph_output = .true.
1625 else
1626 45 this%use_graph_output = .false.
1627 end if
1628
1629
1630 !---------------------------------------------------------------------------
1631 ! Confirm input_shape of each layer matches data going into it
1632 !---------------------------------------------------------------------------
1633
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 54 times.
194 do i = 1, size(this%vertex_order, dim = 1)
1634
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
140 vertex_idx = this%vertex_order(i)
1635
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
140 layer_id = this%auto_graph%vertex(vertex_idx)%id
1636
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
✓ Branch 6 taken 54 times.
✓ Branch 7 taken 86 times.
140 if(this%model(layer_id)%layer%type.eq."inpt") cycle
1637
1638 ! Get all parent vertices that feed into this layer
1639 parent_vertices = pack( &
1640 516 [(j, j=1,size(this%auto_graph%adjacency(:,vertex_idx)))], &
1641 516 this%auto_graph%adjacency(:,vertex_idx) .ne. 0 &
1642
24/40
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 86 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 86 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 86 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 86 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 86 times.
✓ Branch 21 taken 302 times.
✓ Branch 22 taken 86 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 86 times.
✓ Branch 25 taken 302 times.
✓ Branch 26 taken 86 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 86 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 86 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 86 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 86 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 86 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 86 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 86 times.
✓ Branch 47 taken 302 times.
✓ Branch 48 taken 86 times.
✓ Branch 50 taken 86 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 47 times.
✓ Branch 53 taken 39 times.
992 )
1643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 if(size(parent_vertices).eq.0) cycle
1644 172 select type( layer => this%model(layer_id)%layer )
1645 class is(merge_layer_type)
1646 operator = layer%merge_mode
1647 class default
1648
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 if(size(parent_vertices).gt.1)then
1649 call stop_program( &
1650 "layer "//trim(layer%name)// &
1651 " is not a merge layer but has multiple inputs" &
1652 )
1653 return
1654 end if
1655 end select
1656
1657 ! Calculate expected input size from parent layers
1658 86 num_inputs = 0
1659
2/2
✓ Branch 0 taken 86 times.
✓ Branch 1 taken 86 times.
172 do j = 1, size(parent_vertices)
1660
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
86 parent_vertex = parent_vertices(j)
1661
1662 86 select case(operator)
1663 case(1) ! pointwise - all inputs should have same size
1664
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
42 if(num_inputs.eq.0)then
1665
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 18 times.
21 if(this%model(layer_id)%layer%use_graph_input)then
1666
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 num_inputs = this%model(parent_vertex)%layer%output_shape(1)
1667 else
1668
8/14
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 18 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 18 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 18 times.
✓ Branch 18 taken 34 times.
✓ Branch 19 taken 18 times.
52 num_inputs = product(this%model(parent_vertex)%layer%output_shape)
1669 end if
1670 end if
1671 case(2) ! concatenate
1672
2/9
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
86 if(this%model(layer_id)%layer%use_graph_input)then
1673 num_inputs = num_inputs + &
1674 this%model(parent_vertex)%layer%output_shape(1)
1675 else
1676 num_inputs = num_inputs + &
1677 product(this%model(parent_vertex)%layer%output_shape)
1678 end if
1679 end select
1680 end do
1681
1682 ! Verify calculated input size matches layer's expected input size
1683
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
✓ Branch 6 taken 19 times.
✓ Branch 7 taken 67 times.
140 if(this%model(layer_id)%layer%use_graph_input)then
1684
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 19 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 19 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 19 times.
19 if(num_inputs.ne.this%model(layer_id)%layer%input_shape(1) .and. &
1685 num_inputs.ne.0)then
1686 write(*,*) "Expected:", num_inputs, "Got:", &
1687 this%model(layer_id)%layer%input_shape(1)
1688 call stop_program( &
1689 "input_shape of layer "//&
1690 trim(this%model(layer_id)%layer%name)// &
1691 " does not match data going into it" &
1692 )
1693 end if
1694 else
1695
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 67 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 67 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 67 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 67 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 67 times.
✓ Branch 18 taken 103 times.
✓ Branch 19 taken 67 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 67 times.
170 if(num_inputs.ne.product(this%model(layer_id)%layer%input_shape) .and. &
1696 num_inputs.ne.0)then
1697 write(*,*) "Expected:", num_inputs, "Got:", &
1698 product(this%model(layer_id)%layer%input_shape)
1699 call stop_program( &
1700 "input_shape of layer "//&
1701 trim(this%model(layer_id)%layer%name)// &
1702 " does not match data going into it" &
1703 )
1704 end if
1705 end if
1706
1707 end do
1708
1709 !---------------------------------------------------------------------------
1710 ! Initialise optimiser
1711 !---------------------------------------------------------------------------
1712 54 this%num_params = this%get_num_params()
1713
2/4
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
54 if(present(optimiser))then
1714
7/10
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 53 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 53 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 53 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
55 this%optimiser = optimiser
1715 end if
1716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if(.not.allocated(this%optimiser))then
1717 call stop_program("No optimiser is defined for the network")
1718 return
1719 else
1720 54 call this%optimiser%init(num_params=this%num_params)
1721 end if
1722
1723
1724 !---------------------------------------------------------------------------
1725 ! Pre-compute forward pass navigation
1726 !---------------------------------------------------------------------------
1727 block
1728 integer :: nv, l_idx, v_idx, lid, parent_v
1729 54 nv = size(this%vertex_order, 1)
1730
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
54 if(allocated(this%fwd_layer_id)) deallocate(this%fwd_layer_id)
1731
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
54 if(allocated(this%fwd_num_inputs)) deallocate(this%fwd_num_inputs)
1732
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
54 if(allocated(this%fwd_parent_id)) deallocate(this%fwd_parent_id)
1733
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
54 if(allocated(this%fwd_layer_type)) deallocate(this%fwd_layer_type)
1734
7/14
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 54 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 54 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 54 times.
54 allocate(this%fwd_layer_id(nv))
1735
7/14
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 54 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 54 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 54 times.
54 allocate(this%fwd_num_inputs(nv))
1736
7/14
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 54 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 54 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 54 times.
54 allocate(this%fwd_parent_id(nv))
1737
7/14
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 54 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 54 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 54 times.
54 allocate(this%fwd_layer_type(nv))
1738
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 54 times.
194 this%fwd_parent_id = 0
1739
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 54 times.
194 do l_idx = 1, nv
1740
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
140 v_idx = this%vertex_order(l_idx)
1741
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
140 lid = this%auto_graph%vertex(v_idx)%id
1742
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
140 this%fwd_layer_id(l_idx) = lid
1743 280 this%fwd_num_inputs(l_idx) = &
1744
12/20
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 140 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 140 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 140 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 140 times.
✓ Branch 18 taken 442 times.
✓ Branch 19 taken 140 times.
✓ Branch 20 taken 86 times.
✓ Branch 21 taken 356 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 140 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 140 times.
582 count(this%auto_graph%adjacency(:,v_idx).gt.0)
1745
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 140 times.
✓ Branch 6 taken 86 times.
✓ Branch 7 taken 54 times.
140 if(this%fwd_num_inputs(l_idx).eq.1)then
1746 parent_v = maxloc( &
1747
11/18
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 86 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 86 times.
✓ Branch 12 taken 86 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 86 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 86 times.
✓ Branch 20 taken 302 times.
✓ Branch 21 taken 86 times.
✓ Branch 22 taken 155 times.
✓ Branch 23 taken 147 times.
388 this%auto_graph%adjacency(:,v_idx), dim=1)
1748 172 this%fwd_parent_id(l_idx) = &
1749
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 86 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 86 times.
86 this%auto_graph%vertex(parent_v)%id
1750 end if
1751 ! Determine layer type: 0=input, 1=merge, 2=default
1752 54 select type(layer => this%model(lid)%layer)
1753 class is(input_layer_type)
1754
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 54 times.
54 this%fwd_layer_type(l_idx) = 0
1755 class is(merge_layer_type)
1756 this%fwd_layer_type(l_idx) = 1
1757 class default
1758
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
86 this%fwd_layer_type(l_idx) = 2
1759 end select
1760 end do
1761 end block
1762
1763
1764 !---------------------------------------------------------------------------
1765 ! Pre-compute parameter segment layout
1766 !---------------------------------------------------------------------------
1767 block
1768 integer :: l_idx, p_idx, seg_count, s_idx, e_idx
1769 ! First pass: count segments
1770 54 seg_count = 0
1771
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 54 times.
194 do l_idx = 1, this%num_layers
1772 54 select type(current => this%model(l_idx)%layer)
1773 class is(learnable_layer_type)
1774 77 seg_count = seg_count + size(current%params)
1775 end select
1776 end do
1777 54 this%param_num_segments = seg_count
1778
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
54 if(allocated(this%param_seg_layer)) deallocate(this%param_seg_layer)
1779
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
54 if(allocated(this%param_seg_pidx)) deallocate(this%param_seg_pidx)
1780
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
54 if(allocated(this%param_seg_start)) deallocate(this%param_seg_start)
1781
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
54 if(allocated(this%param_seg_end)) deallocate(this%param_seg_end)
1782
7/14
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 54 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 54 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 54 times.
54 allocate(this%param_seg_layer(seg_count))
1783
7/14
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 54 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 54 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 54 times.
54 allocate(this%param_seg_pidx(seg_count))
1784
7/14
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 54 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 54 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 54 times.
54 allocate(this%param_seg_start(seg_count))
1785
7/14
✓ Branch 0 taken 54 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 54 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 54 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 54 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 54 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 54 times.
54 allocate(this%param_seg_end(seg_count))
1786 ! Second pass: fill layout
1787 54 seg_count = 0
1788 54 e_idx = 0
1789
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 54 times.
194 do l_idx = 1, this%num_layers
1790 54 select type(current => this%model(l_idx)%layer)
1791 class is(learnable_layer_type)
1792
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 77 times.
223 do p_idx = 1, size(current%params)
1793 146 seg_count = seg_count + 1
1794 146 s_idx = e_idx + 1
1795
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 146 times.
146 e_idx = e_idx + size(current%params(p_idx)%val, 1)
1796
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 146 times.
146 this%param_seg_layer(seg_count) = l_idx
1797
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 146 times.
146 this%param_seg_pidx(seg_count) = p_idx
1798
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 146 times.
146 this%param_seg_start(seg_count) = s_idx
1799
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 146 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 146 times.
223 this%param_seg_end(seg_count) = e_idx
1800 end do
1801 end select
1802 end do
1803 end block
1804
1805
1806 !---------------------------------------------------------------------------
1807 ! Set batch size, if provided
1808 !---------------------------------------------------------------------------
1809
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 9 times.
54 if(present(batch_size)) this%batch_size = batch_size
1810
1811
13/26
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 54 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 54 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 17 taken 54 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✓ Branch 20 taken 53 times.
✓ Branch 21 taken 1 times.
✓ Branch 22 taken 53 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 54 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 54 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 54 times.
108 end subroutine compile
1812 !###############################################################################
1813
1814
1815 !###############################################################################
1816 1249 module subroutine set_batch_size(this, batch_size)
1817 !! Set the batch size for the network
1818 implicit none
1819
1820 ! Arguments
1821 class(network_type), intent(inout) :: this
1822 !! Instance of network
1823 integer, intent(in) :: batch_size
1824 !! Batch size
1825
1826 ! Local variables
1827 integer :: l
1828 !! Loop index
1829
1830
1831 1249 this%batch_size = batch_size
1832
1833 1249 end subroutine set_batch_size
1834 !###############################################################################
1835
1836
1837 !###############################################################################
1838 module subroutine reset_state(this)
1839 !! Reset the hidden state of all layers in the network
1840 implicit none
1841
1842 ! Arguments
1843 class(network_type), intent(inout) :: this
1844 !! Instance of network
1845
1846 ! Local variables
1847 integer :: l
1848 !! Loop index
1849
1850 do l = 1, size(this%model, dim = 1)
1851 select type( layer => this%model(l)%layer )
1852 class is(recurrent_layer_type)
1853 call layer%reset_state()
1854 end select
1855 end do
1856
1857 end subroutine reset_state
1858 !###############################################################################
1859
1860
1861 !###############################################################################
1862
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 605 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
605 module subroutine set_training_mode(this, mode_store, layer_indices)
1863 !! Put the network in training mode.
1864 implicit none
1865
1866 ! Arguments
1867 class(network_type), intent(inout) :: this
1868 !! Instance of network
1869 logical, dimension(:), allocatable, intent(out), optional :: mode_store
1870 !! Optional array to store the training mode of each layer
1871 integer, dimension(:), intent(in), optional :: layer_indices
1872 !! Optional array of layer indices to set to training mode.
1873 !! If not provided, all layers will be set to training mode.
1874
1875 ! Local variables
1876 integer :: l
1877 !! Loop index
1878
1879
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 605 times.
605 if(.not.allocated(this%model)) return
1880
9/16
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 600 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 5 times.
605 if(present(mode_store)) allocate(mode_store(this%num_layers))
1881
2/2
✓ Branch 0 taken 1813 times.
✓ Branch 1 taken 605 times.
2418 do l = 1, this%num_layers
1882
6/10
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1800 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 13 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 13 times.
1813 if(present(mode_store)) mode_store(l) = this%model(l)%layer%inference
1883
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1813 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1813 times.
1813 this%model(l)%layer%inference = .false.
1884
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1813 times.
1813 if(present(layer_indices))then
1885 if(any(layer_indices.eq.l))then
1886 this%model(l)%layer%inference = .false.
1887 end if
1888 else
1889
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1813 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1813 times.
1813 this%model(l)%layer%inference = .false.
1890 end if
1891 end do
1892
1893 end subroutine set_training_mode
1894 !-------------------------------------------------------------------------------
1895
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 636 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
636 module subroutine set_inference_mode(this, mode_store, layer_indices)
1896 !! Put the network in inference mode.
1897 implicit none
1898
1899 ! Arguments
1900 class(network_type), intent(inout) :: this
1901 !! Instance of network
1902 logical, dimension(:), allocatable, intent(out), optional :: mode_store
1903 !! Optional array to store the training mode of each layer
1904 integer, dimension(:), intent(in), optional :: layer_indices
1905 !! Optional array of layer indices to set to inference mode.
1906 !! If not provided, all layers will be set to inference mode.
1907
1908 ! Local variables
1909 integer :: l
1910 !! Loop index
1911
1912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 636 times.
636 if(.not.allocated(this%model)) return
1913
9/16
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 619 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 17 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 17 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 17 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 17 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 17 times.
636 if(present(mode_store)) allocate(mode_store(this%num_layers))
1914
2/2
✓ Branch 0 taken 1891 times.
✓ Branch 1 taken 636 times.
2527 do l = 1, this%num_layers
1915
6/10
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 1855 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 36 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 36 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 36 times.
1891 if(present(mode_store)) mode_store(l) = this%model(l)%layer%inference
1916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1891 times.
1891 if(present(layer_indices))then
1917 if(any(layer_indices.eq.l))then
1918 this%model(l)%layer%inference = .true.
1919 end if
1920 else
1921
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1891 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1891 times.
1891 this%model(l)%layer%inference = .true.
1922 end if
1923 end do
1924
1925 end subroutine set_inference_mode
1926 !-------------------------------------------------------------------------------
1927
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 module subroutine restore_mode(this, mode_store)
1928 !! Restore the training/inference mode of each layer from a stored array.
1929 implicit none
1930
1931 ! Arguments
1932 class(network_type), intent(inout) :: this
1933 !! Instance of network
1934 logical, dimension(:), intent(in) :: mode_store
1935 !! Array storing the mode of each layer
1936 !! .true. = inference, .false. = training
1937
1938 ! Local variables
1939 integer :: l
1940 !! Loop index
1941
1942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if(.not.allocated(this%model)) return
1943
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 22 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 22 times.
22 if(size(mode_store) .ne. this%num_layers)then
1944 call stop_program("mode_store size does not match number of layers")
1945 return
1946 end if
1947
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 22 times.
71 do l = 1, this%num_layers
1948
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 49 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 49 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 49 times.
49 this%model(l)%layer%inference = mode_store(l)
1949 end do
1950
1951 end subroutine restore_mode
1952 !###############################################################################
1953
1954
1955 !###############################################################################
1956 module function layer_from_id(this, id) result(layer)
1957 !! Get layer from its ID
1958 implicit none
1959
1960 ! Arguments
1961 class(network_type), intent(in), target :: this
1962 !! Instance of network
1963 integer, intent(in) :: id
1964 !! Layer ID
1965
1966 class(base_layer_type), pointer :: layer
1967 !! Layer
1968
1969 ! Local variables
1970 integer :: i, itmp1
1971 !! Loop index
1972
1973 itmp1 = 0
1974 do i = 1, size(this%model, dim = 1)
1975 if(this%model(i)%layer%id.eq.id)then
1976 if(itmp1.ne.0)then
1977 call stop_program("multiple layers with same ID found")
1978 return
1979 end if
1980 layer => this%model(i)%layer
1981 itmp1 = itmp1 + 1
1982 end if
1983 end do
1984
1985 end function layer_from_id
1986 !###############################################################################
1987
1988
1989 !##############################################################################!
1990 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
1991 !##############################################################################!
1992
1993
1994 !###############################################################################
1995 #ifdef __flang__
1996 module function get_sample_flang( &
1997 input, start_index, end_index, batch_size &
1998 ) result(sample)
1999 !! Get samples of batch size from a real array
2000 implicit none
2001
2002 ! Arguments
2003 integer, intent(in) :: start_index, end_index
2004 !! Start and end indices
2005 integer, intent(in) :: batch_size
2006 !! Batch size
2007 real(real32), dimension(..), intent(in) :: input
2008 !! Input array
2009
2010 real(real32), allocatable :: sample(:,:)
2011 !! Sample array
2012
2013 integer :: num_samples
2014
2015 num_samples = end_index - start_index + 1
2016
2017 select rank(input)
2018 rank(2)
2019 sample = input(:, start_index:end_index)
2020 rank(3)
2021 sample = reshape(input(:, :, start_index:end_index), &
2022 [size(input,1) * size(input,2), num_samples])
2023 rank(4)
2024 sample = reshape(input(:, :, :, start_index:end_index), &
2025 [size(input,1) * size(input,2) * size(input,3), num_samples])
2026 rank(5)
2027 sample = reshape(input(:, :, :, :, start_index:end_index), &
2028 [size(input,1) * size(input,2) * size(input,3) * size(input,4), &
2029 num_samples])
2030 rank(6)
2031 sample = reshape(input(:, :, :, :, :, start_index:end_index), &
2032 [size(input,1) * size(input,2) * size(input,3) * size(input,4) * &
2033 size(input,5), num_samples])
2034 rank default
2035 allocate(sample(0, 0))
2036 end select
2037
2038 end function get_sample_flang
2039 #else
2040 13 module function get_sample_ptr( &
2041 input, start_index, end_index, batch_size &
2042 ) result(sample_ptr)
2043 !! Get samples of batch size from a real array
2044 implicit none
2045
2046 ! Arguments
2047 integer, intent(in) :: start_index, end_index
2048 !! Start and end indices
2049 integer, intent(in) :: batch_size
2050 !! Batch size
2051 real(real32), dimension(..), intent(in), target :: input
2052 !! Input array
2053
2054 real(real32), pointer :: sample_ptr(:,:)
2055 !! Pointer to sample
2056
2057
2058 select rank(input)
2059 rank(2)
2060 sample_ptr(1:size(input(:,1)),1:end_index-start_index+1) => &
2061
15/30
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 13 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 13 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 13 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 13 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 13 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 13 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 13 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 13 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 13 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 13 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 13 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 13 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 13 times.
13 input(:,start_index:end_index)
2062 rank(3)
2063 sample_ptr(1:size(input(:,:,1)),1:end_index-start_index+1) => &
2064 input(:,:,start_index:end_index)
2065 rank(4)
2066 sample_ptr(1:size(input(:,:,:,1)),1:end_index-start_index+1) => &
2067 input(:,:,:,start_index:end_index)
2068 rank(5)
2069 sample_ptr(1:size(input(:,:,:,:,1)),1:end_index-start_index+1) => &
2070 input(:,:,:,:,start_index:end_index)
2071 rank(6)
2072 sample_ptr(1:size(input(:,:,:,:,:,1)),1:end_index-start_index+1) => &
2073 input(:,:,:,:,:,start_index:end_index)
2074 rank default
2075 sample_ptr => null()
2076 end select
2077
2078 13 end function get_sample_ptr
2079 #endif
2080 !-------------------------------------------------------------------------------
2081 1704 module function get_sample_array( &
2082
1/2
✓ Branch 0 taken 1704 times.
✗ Branch 1 not taken.
1704 input, start_index, end_index, batch_size, as_graph &
2083 ) result(sample)
2084 !! Get samples of batch size from a derived type array
2085 implicit none
2086
2087 ! Arguments
2088 integer, intent(in) :: start_index, end_index
2089 !! Start and end indices
2090 integer, intent(in) :: batch_size
2091 !! Batch size
2092 class(array_type), dimension(:,:), intent(in) :: input
2093 !! Input array
2094 logical, intent(in) :: as_graph
2095 !! Boolean whether to treat the input as a graph
2096
2097 type(array_type), dimension(:,:), allocatable :: sample
2098 !! Sample array
2099
2100 ! Local variables
2101 integer :: i, j
2102 !! Loop index
2103
2104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1704 times.
1704 if(as_graph)then
2105 allocate(sample(size(input,1), batch_size))
2106 do i = 1, size(input,1)
2107 do j = start_index, end_index, 1
2108 sample(i, j - start_index + 1)%val = input(i, j)%val
2109 end do
2110 end do
2111 else
2112
40/76
✗ Branch 0 not taken.
✓ Branch 1 taken 1704 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1704 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1704 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1704 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1704 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1704 times.
✓ Branch 18 taken 1704 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1704 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1704 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1704 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1704 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 1704 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 1704 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1704 times.
✓ Branch 40 taken 1704 times.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✓ Branch 43 taken 1704 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 1704 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 1704 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 1704 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1704 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 1704 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 1704 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 1704 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 1704 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 1704 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 1704 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 1704 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 1704 times.
✗ Branch 78 not taken.
✓ Branch 79 taken 1704 times.
✓ Branch 81 taken 1704 times.
✓ Branch 82 taken 1704 times.
✓ Branch 83 taken 1704 times.
✓ Branch 84 taken 1704 times.
✓ Branch 85 taken 1704 times.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✓ Branch 88 taken 1704 times.
✗ Branch 89 not taken.
✓ Branch 90 taken 1704 times.
✗ Branch 91 not taken.
✓ Branch 92 taken 1704 times.
✗ Branch 93 not taken.
✓ Branch 94 taken 1704 times.
✗ Branch 95 not taken.
✓ Branch 96 taken 1704 times.
✗ Branch 97 not taken.
✓ Branch 98 taken 1704 times.
5112 allocate(sample(size(input,1), size(input,2)))
2113
8/14
✗ Branch 0 not taken.
✓ Branch 1 taken 1704 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1704 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1704 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1704 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1704 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1704 times.
✓ Branch 18 taken 1704 times.
✓ Branch 19 taken 1704 times.
3408 do i = 1, size(input,1)
2114
8/14
✗ Branch 0 not taken.
✓ Branch 1 taken 1704 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1704 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1704 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1704 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1704 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1704 times.
✓ Branch 18 taken 1704 times.
✓ Branch 19 taken 1704 times.
5112 do j = 1, size(input,2)
2115
2/4
✗ Branch 5 not taken.
✓ Branch 6 taken 1704 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1704 times.
3408 call sample(i,j)%allocate(array_shape=[input(i,j)%shape, &
2116
16/28
✗ Branch 0 not taken.
✓ Branch 1 taken 1704 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1704 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1704 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1704 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1704 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1704 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1704 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1704 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1704 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1704 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1704 times.
✓ Branch 27 taken 1704 times.
✓ Branch 28 taken 1704 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1704 times.
✓ Branch 31 taken 3408 times.
✓ Branch 32 taken 1704 times.
10224 end_index - start_index + 1])
2117
23/44
✗ Branch 0 not taken.
✓ Branch 1 taken 1704 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1704 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1704 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1704 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1704 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1704 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1704 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1704 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1704 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1704 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1704 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1704 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1704 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1704 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 1704 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 1704 times.
✓ Branch 48 taken 1704 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 1704 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1704 times.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✓ Branch 56 taken 1705 times.
✓ Branch 57 taken 1704 times.
✓ Branch 58 taken 5115 times.
✓ Branch 59 taken 1705 times.
10228 sample(i,j)%val = input(i,j)%val(:,start_index:end_index)
2118 end do
2119 end do
2120 end if
2121
2122 1704 end function get_sample_array
2123 !-------------------------------------------------------------------------------
2124 module function get_sample_graph1d( &
2125 input, start_index, end_index, batch_size &
2126 ) result(sample)
2127 !! Get samples of batch size from a graph
2128 implicit none
2129
2130 ! Arguments
2131 integer, intent(in) :: start_index, end_index
2132 !! Start and end indices
2133 integer, intent(in) :: batch_size
2134 !! Batch size
2135 class(graph_type), dimension(:), intent(in) :: input
2136 !! Input array
2137
2138 type(graph_type), dimension(1, batch_size) :: sample
2139 !! Sample array
2140
2141 sample(1,1:batch_size) = input(start_index:end_index)
2142
2143 end function get_sample_graph1d
2144 !-------------------------------------------------------------------------------
2145 12 module function get_sample_graph2d( &
2146
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 input, start_index, end_index, batch_size &
2147
22/48
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 12 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 12 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 12 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 12 times.
✓ Branch 20 taken 12 times.
✓ Branch 21 taken 12 times.
✓ Branch 22 taken 12 times.
✓ Branch 23 taken 12 times.
✓ Branch 24 taken 12 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 12 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 12 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 12 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 12 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 12 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 12 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 12 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 12 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 12 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✓ Branch 49 taken 12 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
48 ) result(sample)
2148 !! Get samples of batch size from a graph
2149 implicit none
2150
2151 ! Arguments
2152 integer, intent(in) :: start_index, end_index
2153 !! Start and end indices
2154 integer, intent(in) :: batch_size
2155 !! Batch size
2156 class(graph_type), dimension(:,:), intent(in) :: input
2157 !! Input array
2158
2159
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 12 times.
12 type(graph_type), dimension(size(input,1), batch_size) :: sample
2160 !! Sample array
2161
2162
47/110
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 12 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 12 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 12 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 12 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 12 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 12 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 12 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 12 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 12 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 12 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 12 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 12 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 12 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 12 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 12 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 12 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 12 times.
✓ Branch 63 taken 12 times.
✓ Branch 64 taken 12 times.
✓ Branch 65 taken 12 times.
✓ Branch 66 taken 12 times.
✓ Branch 67 taken 12 times.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✓ Branch 70 taken 12 times.
✗ Branch 71 not taken.
✓ Branch 72 taken 12 times.
✗ Branch 73 not taken.
✓ Branch 74 taken 12 times.
✓ Branch 75 taken 12 times.
✗ Branch 76 not taken.
✓ Branch 77 taken 12 times.
✗ Branch 78 not taken.
✓ Branch 79 taken 12 times.
✗ Branch 80 not taken.
✓ Branch 81 taken 12 times.
✗ Branch 82 not taken.
✓ Branch 83 taken 12 times.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✓ Branch 86 taken 12 times.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✓ Branch 92 taken 12 times.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✓ Branch 97 taken 12 times.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✓ Branch 100 taken 12 times.
✗ Branch 101 not taken.
✓ Branch 102 taken 12 times.
✗ Branch 103 not taken.
✓ Branch 104 taken 12 times.
✗ Branch 105 not taken.
✓ Branch 106 taken 12 times.
✗ Branch 107 not taken.
✓ Branch 108 taken 12 times.
✗ Branch 109 not taken.
✓ Branch 110 taken 12 times.
✗ Branch 111 not taken.
✓ Branch 112 taken 12 times.
✗ Branch 113 not taken.
✓ Branch 114 taken 12 times.
✗ Branch 115 not taken.
✓ Branch 116 taken 12 times.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✓ Branch 124 taken 12 times.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
36 sample(1:size(input,1),1:batch_size) = input(:,start_index:end_index)
2163
2164
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 12 times.
36 end function get_sample_graph2d
2165 !###############################################################################
2166
2167
2168 !###############################################################################
2169 59 pure module function get_num_params(this) result(num_params)
2170 !! Get the number of learnable parameters in the network
2171 implicit none
2172
2173 ! Arguments
2174 class(network_type), intent(in) :: this
2175 !! Instance of network
2176 integer :: num_params
2177 !! Number of parameters
2178
2179 ! Local variables
2180 integer :: l, i
2181 !! Loop index
2182
2183 59 num_params = 0
2184
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 59 times.
212 do l = 1, this%num_layers
2185 59 select type(current => this%model(l)%layer)
2186 class is(learnable_layer_type)
2187
2/2
✓ Branch 0 taken 161 times.
✓ Branch 1 taken 85 times.
246 do i = 1, size(current%params)
2188
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 161 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 161 times.
246 num_params = num_params + size(current%params(i)%val, 1)
2189 end do
2190 end select
2191 end do
2192
2193 59 end function get_num_params
2194 !###############################################################################
2195
2196
2197 !###############################################################################
2198
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 pure module function get_params(this) result(params)
2199 !! Get learnable parameters
2200 implicit none
2201
2202 ! Arguments
2203 class(network_type), intent(in) :: this
2204 !! Instance of network
2205 real(real32), dimension(this%num_params) :: params
2206 !! Parameters
2207
2208 ! Local variables
2209 integer :: l, i, start_idx, end_idx
2210 !! Loop index
2211
2212 3 start_idx = 0
2213 3 end_idx = 0
2214
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 do l = 1, this%num_layers
2215 3 select type(current => this%model(l)%layer)
2216 class is(learnable_layer_type)
2217
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
11 do i = 1, size(current%params)
2218 7 start_idx = end_idx + 1
2219
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
7 end_idx = end_idx + size(current%params(i)%val, 1)
2220
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 7 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 7 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 7 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 7 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 7 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 7 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 7 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 7 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 7 times.
✓ Branch 39 taken 476 times.
✓ Branch 40 taken 7 times.
487 params(start_idx:end_idx) = current%params(i)%val(:,1)
2221 end do
2222 end select
2223 end do
2224
2225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 end function get_params
2226 !###############################################################################
2227
2228
2229 !###############################################################################
2230 module subroutine set_params(this, params)
2231 !! Set learnable parameters
2232 implicit none
2233
2234 ! Arguments
2235 class(network_type), intent(inout) :: this
2236 !! Instance of network
2237 real(real32), dimension(this%num_params), intent(in) :: params
2238 !! Parameters
2239
2240 ! Local variables
2241 integer :: l, i, start_idx, end_idx
2242 !! Loop index
2243
2244 start_idx = 0
2245 end_idx = 0
2246 do l = 1, this%num_layers
2247 select type(current => this%model(l)%layer)
2248 class is(learnable_layer_type)
2249 do i = 1, size(current%params)
2250 start_idx = end_idx + 1
2251 end_idx = end_idx + size(current%params(i)%val, 1)
2252 current%params(i)%val(:,1) = params(start_idx:end_idx)
2253 end do
2254 ! call current%set_params(params(start_idx:end_idx))
2255 end select
2256 end do
2257
2258 end subroutine set_params
2259 !###############################################################################
2260
2261
2262 !###############################################################################
2263 pure module function get_gradients(this) result(gradients)
2264 !! Get gradients
2265 implicit none
2266
2267 ! Arguments
2268 class(network_type), intent(in) :: this
2269 !! Instance of network
2270 real(real32), dimension(this%num_params) :: gradients
2271 !! Gradients
2272
2273 ! Local variables
2274 integer :: l, i, start_idx, end_idx
2275 !! Loop index
2276
2277 start_idx = 0
2278 end_idx = 0
2279 do l = 1, this%num_layers
2280 select type(current => this%model(l)%layer)
2281 class is(learnable_layer_type)
2282 do i = 1, size(current%params)
2283 if(associated(current%params(i)%grad))then
2284 start_idx = end_idx + 1
2285 end_idx = end_idx + size(current%params(i)%val, 1)
2286 gradients(start_idx:end_idx) = [ &
2287 sum(current%params(i)%grad%val, dim=2) / &
2288 real(size(current%params(i)%grad%val, dim=2), real32) &
2289 ]
2290 end if
2291 end do
2292 end select
2293 end do
2294 call this%optimiser%clip_dict%apply(size(gradients),gradients)
2295
2296 end function get_gradients
2297 !###############################################################################
2298
2299
2300 !###############################################################################
2301 module subroutine set_gradients(this, gradients)
2302 !! Set gradients
2303 implicit none
2304
2305 ! Arguments
2306 class(network_type), intent(inout) :: this
2307 !! Instance of network
2308 real(real32), dimension(..), intent(in) :: gradients
2309 !! Gradients
2310
2311 ! Local variables
2312 integer :: l, start_idx, end_idx
2313 !! Loop index
2314
2315 start_idx = 0
2316 end_idx = 0
2317 do l = 1, this%num_layers
2318 select type(current => this%model(l)%layer)
2319 class is(learnable_layer_type)
2320 start_idx = end_idx + 1
2321 end_idx = end_idx + current%num_params
2322 select rank(gradients)
2323 rank(0)
2324 call current%set_gradients(gradients)
2325 rank(1)
2326 call current%set_gradients(gradients(start_idx:end_idx))
2327 end select
2328 end select
2329 end do
2330
2331 end subroutine set_gradients
2332 !###############################################################################
2333
2334
2335 !###############################################################################
2336 1114 module subroutine reset_gradients(this)
2337 !! Reset gradients
2338 implicit none
2339
2340 ! Arguments
2341 class(network_type), intent(inout) :: this
2342 !! Instance of network
2343
2344 ! Local variables
2345 integer :: l, i
2346 !! Loop index
2347
2348
2/2
✓ Branch 0 taken 3330 times.
✓ Branch 1 taken 1114 times.
4444 do l = 1, this%num_layers
2349 1114 select type(current => this%model(l)%layer)
2350 class is(learnable_layer_type)
2351
2/2
✓ Branch 0 taken 4427 times.
✓ Branch 1 taken 2216 times.
6643 do i = 1, size(current%params)
2352
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
6643 call current%params(i)%zero_grad()
2353 end do
2354 end select
2355 end do
2356
2357 1114 end subroutine reset_gradients
2358 !###############################################################################
2359
2360
2361 !###############################################################################
2362 module function get_output_shape(this) result(output_shape)
2363 !! Get the output of the network
2364 implicit none
2365
2366 ! Arguments
2367 class(network_type), intent(in) :: this
2368 !! Instance of network
2369 integer, dimension(2) :: output_shape
2370 !! Output shape
2371
2372 ! Local variables
2373 integer :: i, layer_idx
2374 !! Loop indices
2375
2376
2377 ! array data: [ layer idx, empty ]
2378 ! graph data: [ vertex/edge idx, sample idx]
2379
2380 if(this%use_graph_output)then
2381 output_shape = [2, this%batch_size]
2382 do i = 1, size(this%leaf_vertices,1), 1
2383 layer_idx = this%auto_graph%vertex(this%leaf_vertices(i))%id
2384 if(size(this%model(layer_idx)%layer%output,2).ne.this%batch_size)then
2385 call stop_program( &
2386 "Inconsistent batch size in output layers" &
2387 )
2388 return
2389 end if
2390 output_shape(1) = output_shape(1) + &
2391 size( this%model(layer_idx)%layer%output, 1 )
2392 end do
2393 else
2394 output_shape = [0, 1]
2395 do i = 1, size(this%leaf_vertices,1)
2396 layer_idx = this%auto_graph%vertex(this%leaf_vertices(i))%id
2397 if(size(this%model(layer_idx)%layer%output,2).ne.1)then
2398 call stop_program( &
2399 "Inconsistent size of dimension 2 in output layers" &
2400 )
2401 return
2402 end if
2403 output_shape(1) = &
2404 output_shape(1) + size( this%model(layer_idx)%layer%output, 1 )
2405 end do
2406 end if
2407
2408 end function get_output_shape
2409 !-------------------------------------------------------------------------------
2410 3 module function get_output(this) result(output)
2411 !! Get the output of the network
2412 implicit none
2413
2414 ! Arguments
2415 class(network_type), intent(in) :: this
2416 !! Instance of network
2417 type(array_type), dimension(:,:), allocatable :: output
2418 !! Output
2419
2420 ! Local variables
2421 integer :: i, start_idx, end_idx, layer_idx, output_id
2422 !! Loop indices
2423 integer, dimension(2) :: output_shape
2424 !! Output shape
2425 3 integer, dimension(this%num_outputs) :: output_ids
2426 !! Output IDs
2427
2428
2429 ! array data: [ layer idx, empty ]
2430 ! graph data: [ vertex/edge idx, sample idx]
2431
2432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(this%use_graph_output)then
2433 output_shape = [2, this%batch_size]
2434 do i = 1, size(this%leaf_vertices,1), 1
2435 layer_idx = this%auto_graph%vertex(this%leaf_vertices(i))%id
2436 if(size(this%model(layer_idx)%layer%output,2).ne.this%batch_size)then
2437 call stop_program( &
2438 "Inconsistent batch size in output layers" &
2439 )
2440 return
2441 end if
2442 output_id = this%model(layer_idx)%layer%id
2443 output_ids(output_id) = size( this%model(layer_idx)%layer%output, 1 )
2444 output_shape(1) = output_shape(1) + output_ids(output_id)
2445 end do
2446 allocate(output(output_shape(1), output_shape(2)))
2447 do i = 1, size(this%leaf_vertices,1)
2448 layer_idx = this%auto_graph%vertex(this%leaf_vertices(i))%id
2449 output_id = sum(output_ids(1:this%model(layer_idx)%layer%id-1)) + 1
2450 output(output_id,:) = this%model(layer_idx)%layer%output(1,:)
2451 if(output_ids(this%model(layer_idx)%layer%id).gt.1)then
2452 output(output_id+1,:) = this%model(layer_idx)%layer%output(2,:)
2453 end if
2454 end do
2455 else
2456 3 output_shape = [0, 1]
2457
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 do i = 1, size(this%leaf_vertices,1)
2458
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 layer_idx = this%auto_graph%vertex(this%leaf_vertices(i))%id
2459
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
3 if(size(this%model(layer_idx)%layer%output,2).ne.1)then
2460 call stop_program( &
2461 "Inconsistent size of dimension 2 in output layers" &
2462 )
2463 return
2464 end if
2465 output_shape(1) = &
2466
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 output_shape(1) + size( this%model(layer_idx)%layer%output, 1 )
2467
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 output_id = this%model(layer_idx)%layer%id
2468
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
6 output_ids(output_id) = size( this%model(layer_idx)%layer%output, 1 )
2469 end do
2470
28/52
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 3 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 3 times.
✓ Branch 45 taken 3 times.
✓ Branch 46 taken 3 times.
✓ Branch 47 taken 3 times.
✓ Branch 48 taken 3 times.
✓ Branch 49 taken 3 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✓ Branch 52 taken 3 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 3 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 3 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 3 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 3 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 3 times.
9 allocate(output(output_shape(1), output_shape(2)))
2471 3 start_idx = 1
2472 3 end_idx = 0
2473
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 do i = 1, size(this%leaf_vertices,1)
2474
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 layer_idx = this%auto_graph%vertex(this%leaf_vertices(i))%id
2475
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 output_id = this%model(layer_idx)%layer%id
2476
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 end_idx = end_idx + output_ids(output_id)
2477
31/60
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 3 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 3 times.
✓ Branch 46 taken 3 times.
✓ Branch 47 taken 3 times.
✓ Branch 48 taken 3 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 3 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 3 times.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✓ Branch 55 taken 3 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 3 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 3 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 3 times.
✓ Branch 62 taken 3 times.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✓ Branch 65 taken 3 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 3 times.
✗ Branch 68 not taken.
✓ Branch 69 taken 3 times.
✗ Branch 70 not taken.
✓ Branch 71 taken 3 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 3 times.
✗ Branch 74 not taken.
✓ Branch 75 taken 3 times.
6 output(start_idx:end_idx,1) = this%model(layer_idx)%layer%output(:,1)
2478 6 start_idx = end_idx + 1
2479 end do
2480 end if
2481
2482 3 end function get_output
2483 !-------------------------------------------------------------------------------
2484 2 module subroutine extract_output_real(this, output)
2485 !! Get the output of the network as real array
2486 implicit none
2487
2488 ! Arguments
2489 class(network_type), intent(in) :: this
2490 ! Instance of network
2491 real(real32), dimension(..), allocatable, intent(out) :: output
2492 !! Output
2493
2494 ! Local variables
2495 integer :: layer_id
2496 !! Layer ID
2497 character(len=10) :: rank_str
2498 !! String for rank
2499
2500 ! check if number of leaf vertices is 1
2501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(size(this%leaf_vertices,1).gt.1)then
2502 call print_warning("Output extraction to real array only works for single &
2503 &output networks")
2504 return
2505 end if
2506
2507 ! Get output from the first (and only) leaf vertex
2508
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
2 layer_id = this%auto_graph%vertex(this%leaf_vertices(1))%id
2509
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2 times.
2 call this%model(layer_id)%layer%output(1,1)%extract(output)
2510
2511 end subroutine extract_output_real
2512 !###############################################################################
2513
2514
2515 !##############################################################################!
2516 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
2517 !##############################################################################!
2518
2519
2520 !###############################################################################
2521
1/2
✓ Branch 0 taken 1716 times.
✗ Branch 1 not taken.
1716 module function accuracy_eval(this, output, start_index, end_index) &
2522 result(accuracy)
2523 !! Get the loss for the output
2524 implicit none
2525
2526 ! Arguments
2527 class(network_type), intent(in) :: this
2528 !! Instance of network
2529 class(*), dimension(:,:), intent(in) :: output
2530 !! Output
2531 integer, intent(in) :: start_index, end_index
2532 !! Start and end batch indices
2533
2534 real(real32) :: accuracy
2535 !! Loss value
2536
2537 ! Local variables
2538 integer :: s, s_idx
2539 !! Loop index
2540
2541 1716 accuracy = 0._real32
2542 select type(output)
2543 type is(graph_type)
2544
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 6 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
✓ Branch 14 taken 6 times.
✓ Branch 15 taken 6 times.
12 do s = start_index, end_index, 1
2545 6 s_idx = s - start_index + 1
2546 accuracy = accuracy + sum( this%get_accuracy( &
2547 48 this%model(this%leaf_vertices(1))%layer%output(1,s_idx)%val, &
2548 output(1,s)%vertex_features &
2549
23/44
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 6 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 6 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 6 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 6 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 6 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 6 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 6 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 6 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 6 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 6 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 6 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 6 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 6 times.
✓ Branch 45 taken 30 times.
✓ Branch 46 taken 6 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 6 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 6 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 6 times.
36 ) ) / output(1,s)%num_vertices
2550
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
6 if( &
2551
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 this%model(this%leaf_vertices(1))%layer%output_shape(2).gt.0 &
2552 6 )then
2553 accuracy = accuracy + sum( this%get_accuracy( &
2554 this%model(this%leaf_vertices(1))%layer%output(2,s_idx)%val, &
2555 output(1,s)%edge_features &
2556 ) ) / output(1,s)%num_edges
2557 end if
2558 end do
2559 type is(real(real32))
2560 accuracy = sum( &
2561 this%get_accuracy( &
2562 16 this%model(this%leaf_vertices(1))%layer%output(1,1)%val, &
2563 output(:,start_index:end_index:1) &
2564
31/60
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 2 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 2 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 2 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 2 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 2 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 2 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 2 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 2 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 2 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 2 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 2 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 2 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 2 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 2 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 2 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 2 times.
✗ Branch 62 not taken.
✓ Branch 63 taken 2 times.
✗ Branch 64 not taken.
✓ Branch 65 taken 2 times.
✓ Branch 67 taken 2 times.
✓ Branch 68 taken 2 times.
4 ))
2565 type is(integer)
2566 accuracy = sum( &
2567 this%get_accuracy( &
2568 this%model(this%leaf_vertices(1))%layer%output(1,1)%val, &
2569 real(output(:,start_index:end_index:1),real32) &
2570 ))
2571 class is(array_type)
2572 accuracy = sum( &
2573 this%get_accuracy( &
2574 13664 this%model(this%leaf_vertices(1))%layer%output(1,1)%val, &
2575 output(1,1)%val(:,start_index:end_index:1) &
2576
36/70
✗ Branch 0 not taken.
✓ Branch 1 taken 1708 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1708 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1708 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1708 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1708 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1708 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1708 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1708 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1708 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1708 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1708 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1708 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1708 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 1708 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 1708 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 1708 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 1708 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 1708 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 1708 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 1708 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 1708 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 1708 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 1708 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 1708 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 1708 times.
✗ Branch 64 not taken.
✓ Branch 65 taken 1708 times.
✗ Branch 67 not taken.
✓ Branch 68 taken 1708 times.
✗ Branch 70 not taken.
✓ Branch 71 taken 1708 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 1708 times.
✗ Branch 74 not taken.
✓ Branch 75 taken 1708 times.
✗ Branch 76 not taken.
✓ Branch 77 taken 1708 times.
✗ Branch 78 not taken.
✓ Branch 79 taken 1708 times.
✗ Branch 80 not taken.
✓ Branch 81 taken 1708 times.
✗ Branch 82 not taken.
✓ Branch 83 taken 1708 times.
✓ Branch 85 taken 1709 times.
✓ Branch 86 taken 1708 times.
3417 ))
2577 end select
2578 1716 accuracy = accuracy / real(end_index - start_index + 1, real32)
2579
2580 1716 end function accuracy_eval
2581 !###############################################################################
2582
2583
2584 !###############################################################################
2585 1718 module function loss_eval(this, start_index, end_index) result(loss)
2586 !! Get the loss for the output
2587 implicit none
2588
2589 ! Arguments
2590 class(network_type), intent(inout), target :: this
2591 !! Instance of network
2592 integer, intent(in) :: start_index, end_index
2593 !! Start and end batch indices
2594
2595 type(array_type), pointer :: loss
2596 !! Loss value
2597
2598 ! Local variables
2599 integer :: i, s
2600 !! Loop index
2601 1718 type(array_type), pointer :: expected(:,:), predicted(:,:)
2602
2603
2604 1718 if(this%use_graph_output)then
2605 expected(1:2, 1: end_index - start_index + 1) => &
2606
9/18
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 6 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 6 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 6 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 6 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 6 times.
6 this%expected_array( :, start_index:end_index )
2607 else
2608
27/50
✓ Branch 0 taken 1712 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1712 times.
✓ Branch 4 taken 1712 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1712 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1712 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1712 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1712 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1712 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1712 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1712 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1712 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1712 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1712 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1712 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1712 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1712 times.
✓ Branch 42 taken 1712 times.
✓ Branch 43 taken 1712 times.
✓ Branch 44 taken 1712 times.
✓ Branch 45 taken 1712 times.
✓ Branch 46 taken 1712 times.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✓ Branch 49 taken 1712 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 1712 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 1712 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 1712 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 1712 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 1712 times.
5136 allocate(expected(size(this%expected_array,1), size(this%expected_array,2)))
2609
2/2
✓ Branch 0 taken 1712 times.
✓ Branch 1 taken 1712 times.
3424 do s = 1, size(this%expected_array,2)
2610
2/2
✓ Branch 0 taken 1712 times.
✓ Branch 1 taken 1712 times.
5136 do i = 1, size(this%expected_array,1)
2611 call expected(i,s)%allocate( &
2612 13696 array_shape = [ &
2613 this%expected_array(i,s)%shape, &
2614 6848 size(this%expected_array(i,s)%val,2) &
2615 ] &
2616
22/40
✗ Branch 0 not taken.
✓ Branch 1 taken 1712 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1712 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1712 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1712 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1712 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1712 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1712 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1712 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1712 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1712 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1712 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1712 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 1712 times.
✓ Branch 35 taken 1712 times.
✓ Branch 36 taken 1712 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1712 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 1712 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 1712 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 1712 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 1712 times.
✓ Branch 51 taken 3424 times.
✓ Branch 52 taken 1712 times.
6848 )
2617 expected(i,s)%val = this%expected_array(i,s)%val(:, &
2618
25/44
✗ Branch 0 not taken.
✓ Branch 1 taken 1712 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1712 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1712 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1712 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1712 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1712 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1712 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1712 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1712 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 1712 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1712 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1712 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 1712 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 1712 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 1712 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 1712 times.
✓ Branch 44 taken 1712 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 1712 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 1709 times.
✓ Branch 49 taken 3 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 3 times.
✓ Branch 52 taken 1713 times.
✓ Branch 53 taken 1712 times.
✓ Branch 54 taken 3430 times.
✓ Branch 55 taken 1713 times.
10276 start_index:end_index:1)
2619 end do
2620 end do
2621 end if
2622
2623
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1718 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1718 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1718 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1718 times.
1718 predicted => this%model(this%leaf_vertices(1))%layer%output
2624 loss => this%loss%compute( &
2625 predicted, &
2626 expected &
2627
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1718 times.
1718 )
2628
2629
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1712 times.
3436 end function loss_eval
2630 !###############################################################################
2631
2632
2633 !##############################################################################!
2634 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
2635 !##############################################################################!
2636
2637
2638 !###############################################################################
2639
1/2
✓ Branch 0 taken 1745 times.
✗ Branch 1 not taken.
1745 module subroutine forward_generic2d(this, input)
2640 !! Forward pass for array derived type input
2641 implicit none
2642
2643 ! Arguments
2644 class(network_type), intent(inout), target :: this
2645 !! Instance of network
2646 class(*), dimension(:,:), intent(in) :: input
2647 !! Input
2648
2649 ! Local variables
2650 integer :: l, i, j, vertex_idx, layer_id, parent_id
2651 !! Loop index and vertex index
2652 integer :: num_input_layers
2653 !! Number of input layers
2654 1745 type(array_type), pointer :: input_ptr(:,:) => null()
2655 1745 type(array_ptr_type), dimension(:), allocatable :: input_list
2656 logical :: use_precomp
2657
2658
2659 select type(input)
2660 type is(graph_type)
2661
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 18 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 18 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 18 times.
✓ Branch 14 taken 18 times.
✓ Branch 15 taken 18 times.
36 do j = 1, this%batch_size
2662
16/30
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 18 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 18 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 18 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 18 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 18 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 18 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 18 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 18 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 18 times.
✓ Branch 36 taken 204 times.
✓ Branch 37 taken 18 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 204 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 18 times.
240 if(any(input(1,j)%adj_ja(1,:).gt.input(1,j)%num_vertices))then
2663 call stop_program( &
2664 "input graph has more vertices than expected" &
2665 )
2666 end if
2667 end do
2668 end select
2669
2670 ! Use pre-computed navigation if available
2671 1745 use_precomp = allocated(this%fwd_layer_id)
2672
2673 ! Forward pass
2674 !---------------------------------------------------------------------------
2675
2/2
✓ Branch 0 taken 5217 times.
✓ Branch 1 taken 1745 times.
6962 do l = 1, size(this%vertex_order,1)
2676
1/2
✓ Branch 0 taken 5217 times.
✗ Branch 1 not taken.
5217 if(use_precomp)then
2677
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5217 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5217 times.
5217 layer_id = this%fwd_layer_id(l)
2678
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5217 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5217 times.
5217 num_input_layers = this%fwd_num_inputs(l)
2679 else
2680 vertex_idx = this%vertex_order(l)
2681 layer_id = this%auto_graph%vertex(vertex_idx)%id
2682 num_input_layers = count(this%auto_graph%adjacency(:,vertex_idx).gt.0)
2683 end if
2684
2685
2/2
✓ Branch 0 taken 1745 times.
✓ Branch 1 taken 3472 times.
5217 if(num_input_layers.eq.0)then
2686 3490 select type(layer => this%model(layer_id)%layer)
2687 class is(input_layer_type)
2688 select type(input)
2689 type is(graph_type)
2690
52/82
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 18 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 18 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 18 times.
✓ Branch 16 taken 18 times.
✓ Branch 17 taken 18 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 18 times.
✓ Branch 20 taken 18 times.
✓ Branch 21 taken 18 times.
✓ Branch 22 taken 18 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 18 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 18 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 18 times.
✓ Branch 30 taken 18 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 18 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 18 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 18 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 18 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 3 times.
✓ Branch 41 taken 15 times.
✓ Branch 42 taken 12 times.
✓ Branch 43 taken 3 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 12 times.
✓ Branch 46 taken 3 times.
✓ Branch 47 taken 15 times.
✓ Branch 48 taken 15 times.
✓ Branch 49 taken 3 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 15 times.
✓ Branch 53 taken 18 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 18 times.
✓ Branch 56 taken 18 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 18 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 18 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 18 times.
✓ Branch 63 taken 18 times.
✗ Branch 64 not taken.
✓ Branch 65 taken 18 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 18 times.
✗ Branch 68 not taken.
✓ Branch 69 taken 18 times.
✗ Branch 70 not taken.
✓ Branch 71 taken 18 times.
✗ Branch 72 not taken.
✓ Branch 73 taken 3 times.
✓ Branch 74 taken 15 times.
✓ Branch 75 taken 3 times.
✗ Branch 76 not taken.
✓ Branch 77 taken 12 times.
✓ Branch 78 taken 3 times.
✗ Branch 79 not taken.
✓ Branch 80 taken 12 times.
✓ Branch 81 taken 3 times.
✓ Branch 82 taken 15 times.
✓ Branch 83 taken 3 times.
✗ Branch 84 not taken.
✓ Branch 85 taken 15 times.
✓ Branch 86 taken 3 times.
✗ Branch 87 not taken.
✓ Branch 88 taken 15 times.
132 call layer%set_input_graph( [ input(layer%index, :) ] )
2691
8/16
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 18 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 18 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 18 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 18 times.
36 cycle
2692 class is(array_type)
2693
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 1712 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1712 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1712 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1712 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1712 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1712 times.
1712 call layer%forward(input(layer%index:layer%index,:))
2694 3424 do concurrent(i=1:size(layer%output,1), j=1:size(layer%output,2))
2695
8/12
✓ Branch 0 taken 1712 times.
✓ Branch 1 taken 1712 times.
✓ Branch 2 taken 1712 times.
✓ Branch 3 taken 1712 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1712 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1712 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1712 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1712 times.
5136 call layer%output(i,j)%set_requires_grad(.false.)
2696 end do
2697
9/18
✗ Branch 0 not taken.
✓ Branch 1 taken 1712 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1712 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1712 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1712 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1712 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1712 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1712 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1712 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1712 times.
3424 cycle
2698 type is(real(real32))
2699
20/36
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 15 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 15 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 15 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 15 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 15 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 15 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 15 times.
✓ Branch 28 taken 15 times.
✓ Branch 29 taken 15 times.
✓ Branch 30 taken 15 times.
✓ Branch 31 taken 15 times.
✓ Branch 32 taken 15 times.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 15 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 15 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 15 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 15 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 15 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 15 times.
45 allocate(input_ptr(1,1))
2700
8/14
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 15 times.
✓ Branch 12 taken 30 times.
✓ Branch 13 taken 15 times.
✓ Branch 14 taken 30 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 30 times.
45 call input_ptr(1,1)%allocate(shape(input))
2701
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 15 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 15 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 15 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 15 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 15 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 15 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 15 times.
15 call input_ptr(1,1)%set(input)
2702 15 call layer%forward(input_ptr)
2703
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 15 times.
15 call layer%output(1,1)%set_requires_grad(.false.)
2704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 deallocate(input_ptr)
2705 15 input_ptr => null()
2706
8/16
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 15 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 15 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 15 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 15 times.
30 cycle
2707 class default
2708 call stop_program( &
2709 "input type for layer "// &
2710 trim(layer%name) // &
2711 " is not supported" &
2712 )
2713 end select
2714 class default
2715 return
2716 end select
2717
1/2
✓ Branch 0 taken 3472 times.
✗ Branch 1 not taken.
3472 elseif(num_input_layers.eq.1)then
2718
1/2
✓ Branch 0 taken 3472 times.
✗ Branch 1 not taken.
3472 if(use_precomp)then
2719
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3472 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3472 times.
3472 parent_id = this%fwd_parent_id(l)
2720 else
2721 vertex_idx = this%vertex_order(l)
2722 j = maxloc( &
2723 this%auto_graph%adjacency(:,vertex_idx), dim=1)
2724 parent_id = this%auto_graph%vertex(j)%id
2725 end if
2726
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3472 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3472 times.
3472 input_ptr => this%model(parent_id)%layer%output
2727 select type(input)
2728 type is(graph_type)
2729
61/100
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 24 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 24 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 24 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 24 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 24 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 24 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 24 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 24 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 24 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 24 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 24 times.
✓ Branch 35 taken 24 times.
✓ Branch 36 taken 24 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 24 times.
✓ Branch 39 taken 24 times.
✓ Branch 40 taken 24 times.
✓ Branch 41 taken 24 times.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✓ Branch 44 taken 24 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 24 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 24 times.
✓ Branch 49 taken 24 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 24 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 24 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 24 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 24 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 9 times.
✓ Branch 60 taken 15 times.
✓ Branch 61 taken 36 times.
✓ Branch 62 taken 9 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 36 times.
✓ Branch 65 taken 9 times.
✓ Branch 66 taken 15 times.
✓ Branch 67 taken 45 times.
✓ Branch 68 taken 9 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 45 times.
✓ Branch 72 taken 24 times.
✗ Branch 73 not taken.
✓ Branch 74 taken 24 times.
✓ Branch 75 taken 24 times.
✗ Branch 76 not taken.
✓ Branch 77 taken 24 times.
✗ Branch 78 not taken.
✓ Branch 79 taken 24 times.
✗ Branch 80 not taken.
✓ Branch 81 taken 24 times.
✓ Branch 82 taken 24 times.
✗ Branch 83 not taken.
✓ Branch 84 taken 24 times.
✗ Branch 85 not taken.
✓ Branch 86 taken 24 times.
✗ Branch 87 not taken.
✓ Branch 88 taken 24 times.
✗ Branch 89 not taken.
✓ Branch 90 taken 24 times.
✗ Branch 91 not taken.
✓ Branch 92 taken 9 times.
✓ Branch 93 taken 15 times.
✓ Branch 94 taken 9 times.
✗ Branch 95 not taken.
✓ Branch 96 taken 36 times.
✓ Branch 97 taken 9 times.
✗ Branch 98 not taken.
✓ Branch 99 taken 36 times.
✓ Branch 100 taken 9 times.
✓ Branch 101 taken 15 times.
✓ Branch 102 taken 9 times.
✗ Branch 103 not taken.
✓ Branch 104 taken 45 times.
✓ Branch 105 taken 9 times.
✗ Branch 106 not taken.
✓ Branch 107 taken 45 times.
300 call this%model(layer_id)%layer%set_graph( [ input(1,:) ] )
2730 end select
2731 else
2732 vertex_idx = this%vertex_order(l)
2733 allocate(input_list(num_input_layers))
2734 i = 0
2735 do j = 1, size(this%vertex_order,1)
2736 if(this%auto_graph%adjacency(j,vertex_idx).gt.0)then
2737 i = i + 1
2738 parent_id = this%auto_graph%vertex(j)%id
2739 input_list(i)%array => this%model(parent_id)%layer%output
2740 end if
2741 end do
2742 end if
2743
2744
1/2
✓ Branch 0 taken 3472 times.
✗ Branch 1 not taken.
5217 if(use_precomp)then
2745
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3472 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3472 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3472 times.
3472 if(this%fwd_layer_type(l).eq.1)then
2746 select type(layer => this%model(layer_id)%layer)
2747 class is(merge_layer_type)
2748 call layer%combine(input_list)
2749 end select
2750 deallocate(input_list)
2751 else
2752
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3472 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3472 times.
3472 call this%model(layer_id)%layer%forward(input_ptr)
2753 3472 input_ptr => null()
2754 end if
2755 else
2756 select type(layer => this%model(layer_id)%layer)
2757 class is(merge_layer_type)
2758 call layer%combine(input_list)
2759 deallocate(input_list)
2760 class default
2761 call layer%forward(input_ptr)
2762 input_ptr => null()
2763 end select
2764 end if
2765
2766 end do
2767
2768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1745 times.
1745 end subroutine forward_generic2d
2769 !-------------------------------------------------------------------------------
2770 module function forward_eval(this, input) result(output)
2771 !! Forward pass for evaluation
2772 implicit none
2773
2774 ! Arguments
2775 class(network_type), intent(inout), target :: this
2776 !! Instance of network
2777 class(*), dimension(:,:), intent(in) :: input
2778 !! Input
2779
2780 type(array_type), pointer :: output(:,:)
2781 !! Output
2782
2783 call this%forward(input)
2784 output => this%model(this%leaf_vertices(1))%layer%output
2785
2786 end function forward_eval
2787 !-------------------------------------------------------------------------------
2788 module function forward_eval_multi(this, input) result(output)
2789 !! Forward pass for evaluation
2790 implicit none
2791
2792 ! Arguments
2793 class(network_type), intent(inout), target :: this
2794 !! Instance of network
2795 class(*), dimension(:,:), intent(in) :: input
2796 !! Input
2797
2798 type(array_ptr_type), pointer :: output(:)
2799 !! Output
2800
2801 ! Local variables
2802 integer :: l
2803 !! Loop index
2804
2805 call this%forward(input)
2806 allocate(output(size(this%leaf_vertices,1)))
2807 do l = 1, size(this%leaf_vertices,1)
2808 output(l)%array => this%model(this%leaf_vertices(l))%layer%output
2809 end do
2810
2811 end function forward_eval_multi
2812 !###############################################################################
2813
2814
2815 !###############################################################################
2816 1114 module subroutine update(this)
2817 !! Update the network
2818 implicit none
2819
2820 ! Arguments
2821 class(network_type), intent(inout) :: this
2822 !! Instance of network
2823 2228 real(real32), dimension(this%num_params) :: params, gradients
2824 !! Parameters and gradients
2825
2826 ! Local variables
2827 integer :: l, i, s, start_idx, end_idx, seg
2828 !! Loop index
2829
2830
2831 !---------------------------------------------------------------------------
2832 ! Increment optimiser iteration counter
2833 !---------------------------------------------------------------------------
2834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1114 times.
1114 if(this%optimiser%lr_decay%iterate_per_epoch)then
2835 if(this%epoch.gt.this%optimiser%epoch)then
2836 this%optimiser%epoch = this%epoch
2837 this%optimiser%iter = this%optimiser%iter + 1
2838 end if
2839 else
2840 1114 this%optimiser%iter = this%optimiser%iter + 1
2841 end if
2842
2843
2844 !---------------------------------------------------------------------------
2845 ! Get learnable parameters and gradients (using pre-computed layout)
2846 !---------------------------------------------------------------------------
2847
1/2
✓ Branch 0 taken 1114 times.
✗ Branch 1 not taken.
1114 if(this%param_num_segments.gt.0 .and. &
2848 allocated(this%param_seg_layer))then
2849
2/2
✓ Branch 0 taken 4427 times.
✓ Branch 1 taken 1114 times.
5541 do seg = 1, this%param_num_segments
2850
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
4427 l = this%param_seg_layer(seg)
2851
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
4427 i = this%param_seg_pidx(seg)
2852
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
4427 start_idx = this%param_seg_start(seg)
2853
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
4427 end_idx = this%param_seg_end(seg)
2854 1114 select type(current => this%model(l)%layer)
2855 class is(learnable_layer_type)
2856
14/26
✗ Branch 1 not taken.
✓ Branch 2 taken 4427 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4427 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4427 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4427 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4427 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 4427 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 4427 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 4427 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 4427 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 4427 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 4427 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 4427 times.
✓ Branch 37 taken 37308 times.
✓ Branch 38 taken 4427 times.
41735 params(start_idx:end_idx) = current%params(i)%val(:,1)
2857
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4427 times.
4427 if(.not.associated(current%params(i)%grad))then
2858 call stop_program( &
2859 "Gradient not allocated for parameters" &
2860 )
2861 end if
2862
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
4427 s = size(current%params(i)%grad%val,2)
2863
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✓ Branch 2 taken 4427 times.
✗ Branch 3 not taken.
8854 if(s.eq.1)then
2864 gradients(start_idx:end_idx) = &
2865
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4427 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4427 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4427 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4427 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 4427 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 4427 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 4427 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 4427 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 4427 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 4427 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 4427 times.
✓ Branch 35 taken 37308 times.
✓ Branch 36 taken 4427 times.
41735 current%params(i)%grad%val(:,1)
2866 else
2867 gradients(start_idx:end_idx) = &
2868 sum(current%params(i)%grad%val, dim=2) / &
2869 real(s, real32)
2870 end if
2871 end select
2872 end do
2873 else
2874 start_idx = 0
2875 end_idx = 0
2876 do l = 1, this%num_layers
2877 select type(current => this%model(l)%layer)
2878 class is(learnable_layer_type)
2879 do i = 1, size(current%params)
2880 start_idx = end_idx + 1
2881 end_idx = end_idx + size(current%params(i)%val, 1)
2882 params(start_idx:end_idx) = current%params(i)%val(:,1)
2883 if(.not.associated(current%params(i)%grad))then
2884 call stop_program( &
2885 "Gradient not allocated for parameters" &
2886 )
2887 end if
2888 select case(size(current%params(i)%grad%val,2))
2889 case(1)
2890 gradients(start_idx:end_idx) = &
2891 current%params(i)%grad%val(:,1)
2892 case default
2893 gradients(start_idx:end_idx) = [ &
2894 sum(current%params(i)%grad%val, dim=2) / &
2895 real( &
2896 size(current%params(i)%grad%val, dim=2), &
2897 real32) &
2898 ]
2899 end select
2900 end do
2901 end select
2902 end do
2903 end if
2904
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1114 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1114 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1114 times.
1114 call this%optimiser%clip_dict%apply(size(gradients),gradients)
2905
2906 !---------------------------------------------------------------------------
2907 ! Update layers of learnable layer types
2908 !---------------------------------------------------------------------------
2909
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 1114 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1114 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1114 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1114 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1114 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1114 times.
1114 call this%optimiser%minimise(params, gradients)
2910
2911 ! Set params back using pre-computed layout
2912
1/2
✓ Branch 0 taken 1114 times.
✗ Branch 1 not taken.
1114 if(this%param_num_segments.gt.0 .and. &
2913 allocated(this%param_seg_layer))then
2914
2/2
✓ Branch 0 taken 4427 times.
✓ Branch 1 taken 1114 times.
5541 do seg = 1, this%param_num_segments
2915
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
4427 l = this%param_seg_layer(seg)
2916
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
4427 i = this%param_seg_pidx(seg)
2917
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
4427 start_idx = this%param_seg_start(seg)
2918
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
4427 end_idx = this%param_seg_end(seg)
2919 1114 select type(current => this%model(l)%layer)
2920 class is(learnable_layer_type)
2921
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 4427 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4427 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4427 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4427 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4427 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4427 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 4427 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 4427 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 4427 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 4427 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 4427 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 4427 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 4427 times.
✓ Branch 39 taken 37308 times.
✓ Branch 40 taken 4427 times.
41735 current%params(i)%val(:,1) = params(start_idx:end_idx)
2922 end select
2923 end do
2924 else
2925 call this%set_params(params)
2926 end if
2927 1114 call this%reset_gradients()
2928
2929 1114 end subroutine update
2930 !###############################################################################
2931
2932
2933 !##############################################################################!
2934 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
2935 !##############################################################################!
2936
2937
2938 !###############################################################################
2939 module subroutine nullify_graph(this)
2940 !! Nullify the input graph
2941 implicit none
2942
2943 ! Arguments
2944 class(network_type), intent(inout) :: this
2945 !! Instance of network
2946
2947 ! Local variables
2948 integer :: l
2949
2950 do l = 1, this%num_layers
2951 call this%model(l)%layer%nullify_graph()
2952 end do
2953
2954 end subroutine nullify_graph
2955 !###############################################################################
2956
2957
2958 !###############################################################################
2959 1111 module subroutine post_epoch_hook(this, epoch, loss, accuracy)
2960 !! Default epoch hook — no-op.
2961 !! Override in a derived type to add custom per-epoch behaviour.
2962 implicit none
2963
2964 ! Arguments
2965 class(network_type), intent(inout) :: this
2966 !! Instance of network
2967 integer, intent(in) :: epoch
2968 !! Current epoch number
2969 real(real32), intent(in) :: loss
2970 !! Mean loss over the epoch
2971 real(real32), intent(in) :: accuracy
2972 !! Mean accuracy over the epoch
2973
2974 1111 end subroutine post_epoch_hook
2975 !###############################################################################
2976
2977
2978 !##############################################################################!
2979 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
2980 !##############################################################################!
2981
2982
2983 !###############################################################################
2984 1230 module function save_input_to_network( this, input ) result(num_samples)
2985 !! Save input to network
2986 implicit none
2987
2988 ! Arguments
2989 class(network_type), intent(inout) :: this
2990 !! Instance of network
2991 class(*), dimension(..), intent(in) :: input
2992 !! Input
2993
2994 integer :: num_samples
2995 !! Number of samples
2996
2997 ! Local variables
2998 integer :: i, j, l, ip, input_rank, num_inputs
2999 !! Loop index
3000 integer :: num_input_layers
3001 !! Number of input layers
3002 logical :: l_valid_rank_type
3003 !! Boolean whether rank type is valid
3004 character(256) :: err_msg
3005 !! Error message
3006
3007 1230 num_samples = get_num_samples(this, input)
3008
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1223 times.
1230 if(num_samples.le.0) return
3009 1223 num_input_layers = size(this%root_vertices, 1)
3010
2/2
✓ Branch 0 taken 1207 times.
✓ Branch 1 taken 16 times.
1223 if(allocated(this%input_array))then
3011
2/2
✓ Branch 0 taken 1207 times.
✓ Branch 1 taken 1207 times.
2414 do i = 1, size(this%input_array, 1)
3012
2/2
✓ Branch 0 taken 1207 times.
✓ Branch 1 taken 1207 times.
3621 do j = 1, size(this%input_array, 2)
3013
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1207 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1207 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1207 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1207 times.
2414 call this%input_array(i,j)%deallocate()
3014 end do
3015 end do
3016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1207 times.
1207 deallocate(this%input_array)
3017 end if
3018
16/40
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1220 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 4 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 4 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 4 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✓ Branch 31 taken 4 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 3 times.
1230 if(allocated(this%input_graph)) deallocate(this%input_graph)
3019
3020 ! Determine the rank of the input
3021 !---------------------------------------------------------------------------
3022 select rank(input)
3023 rank(0)
3024 rank(1)
3025 rank(2)
3026
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1204 times.
1211 select type(input)
3027 class is(array_type)
3028
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1204 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1204 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1204 times.
1204 num_inputs = size(input(1,1)%val, 1)
3029
28/52
✓ Branch 0 taken 1204 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1204 times.
✓ Branch 4 taken 1204 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1204 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1204 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1204 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1204 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1204 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1204 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1204 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1204 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1204 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1204 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1204 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1204 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1204 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 1204 times.
✓ Branch 45 taken 1205 times.
✓ Branch 46 taken 1204 times.
✓ Branch 47 taken 1205 times.
✓ Branch 48 taken 1205 times.
✓ Branch 49 taken 1205 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✓ Branch 52 taken 1205 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 1205 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 1205 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 1205 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 1205 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 1205 times.
3614 allocate(this%input_array(size(input,1), size(input,2)))
3030
2/2
✓ Branch 0 taken 1204 times.
✓ Branch 1 taken 1204 times.
2408 do i = 1, size(input,1)
3031
2/2
✓ Branch 0 taken 1205 times.
✓ Branch 1 taken 1204 times.
3613 do j = 1, size(input,2)
3032
8/16
✗ Branch 0 not taken.
✓ Branch 1 taken 1205 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1205 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1205 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1205 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1205 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1205 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1205 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1205 times.
2409 call this%input_array(i,j)%assign_shallow(input(i,j))
3033 end do
3034 end do
3035
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1204 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1204 times.
2408 return
3036 class default
3037 7 input_rank = rank(input)
3038
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 7 times.
21 num_inputs = size(input) / num_samples
3039
22/40
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 7 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 7 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 7 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 7 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 7 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 7 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 7 times.
✓ Branch 33 taken 7 times.
✓ Branch 34 taken 7 times.
✓ Branch 35 taken 7 times.
✓ Branch 36 taken 7 times.
✓ Branch 37 taken 7 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 7 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 7 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 7 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 7 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 7 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 7 times.
21 allocate(this%input_array(1,1))
3040
6/10
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 7 times.
✓ Branch 12 taken 14 times.
✓ Branch 13 taken 7 times.
21 call this%input_array(1,1)%allocate(array_shape=[num_inputs, num_samples])
3041 end select
3042 rank default
3043 3 input_rank = rank(input)
3044
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 3 times.
15 num_inputs = size(input) / num_samples
3045
22/40
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✓ Branch 33 taken 3 times.
✓ Branch 34 taken 3 times.
✓ Branch 35 taken 3 times.
✓ Branch 36 taken 3 times.
✓ Branch 37 taken 3 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 3 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 3 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 3 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 3 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 3 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 3 times.
9 allocate(this%input_array(1,1))
3046
10/18
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✓ Branch 14 taken 12 times.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 12 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 12 times.
✓ Branch 21 taken 12 times.
✗ Branch 22 not taken.
15 call this%input_array(1,1)%allocate(array_shape=shape(input))
3047 end select
3048 19 l_valid_rank_type = .false.
3049
3050
3051 ! Process input based on its rank
3052 !---------------------------------------------------------------------------
3053 rank_select: select rank(input)
3054 rank(0)
3055 select type(input)
3056 type is(real); exit rank_select
3057 2 class default; l_valid_rank_type = .true.
3058 end select
3059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(num_input_layers.ne.1)then
3060 call stop_program( &
3061 "number of input arrays does not match expected number of &
3062 &input layers" &
3063 )
3064 return
3065 end if
3066
1/3
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
2 select type(input)
3067 class is(array_type)
3068
21/38
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 times.
✓ Branch 31 taken 1 times.
✓ Branch 32 taken 1 times.
✓ Branch 33 taken 1 times.
✓ Branch 34 taken 1 times.
✓ Branch 35 taken 1 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 1 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 1 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 1 times.
3 allocate(this%input_array(1,1))
3069
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
2 call handle_array_type(input, this%input_array(1,1), num_samples)
3070 type is(array_ptr_type)
3071
27/50
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 1 times.
✓ Branch 43 taken 1 times.
✓ Branch 44 taken 1 times.
✓ Branch 45 taken 1 times.
✓ Branch 46 taken 1 times.
✓ Branch 47 taken 1 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 1 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 1 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 1 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 1 times.
3 allocate(this%input_array(size(input%array,1), size(input%array,2)))
3072
3/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
3 do i = 1, size(input%array,1)
3073
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
3 do j = 1, size(input%array,2)
3074 call handle_array_type( &
3075 8 input%array(i,j), this%input_array(i,j), num_samples &
3076
8/16
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
2 )
3077 end do
3078 end do
3079 end select
3080 rank(1)
3081 select type(input)
3082 type is(real(real32))
3083 1 exit rank_select
3084 type is(graph_type)
3085
31/66
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 1 times.
✓ Branch 43 taken 2 times.
✓ Branch 44 taken 1 times.
✓ Branch 45 taken 2 times.
✓ Branch 46 taken 2 times.
✓ Branch 47 taken 2 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 2 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 2 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 2 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 2 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 2 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 2 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 2 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 2 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 2 times.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✓ Branch 72 taken 2 times.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
5 allocate(this%input_graph(num_input_layers, num_samples))
3086
35/88
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✓ Branch 33 taken 2 times.
✓ Branch 34 taken 1 times.
✓ Branch 35 taken 2 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 2 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 2 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 2 times.
✓ Branch 43 taken 2 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 2 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 2 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 2 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 2 times.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✓ Branch 54 taken 2 times.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✓ Branch 60 taken 2 times.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✓ Branch 65 taken 2 times.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✓ Branch 68 taken 2 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 2 times.
✗ Branch 71 not taken.
✓ Branch 72 taken 2 times.
✗ Branch 73 not taken.
✓ Branch 74 taken 2 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 2 times.
✗ Branch 77 not taken.
✓ Branch 78 taken 2 times.
✗ Branch 79 not taken.
✓ Branch 80 taken 2 times.
✗ Branch 81 not taken.
✓ Branch 82 taken 2 times.
✗ Branch 83 not taken.
✓ Branch 84 taken 2 times.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✓ Branch 92 taken 2 times.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
3 this%input_graph(1,:) = input(:)
3087
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
4 return
3088 class default
3089 5 l_valid_rank_type = .true.
3090 end select
3091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(size(input,1).ne.num_input_layers)then
3092 call stop_program( &
3093 "number of input arrays does not match expected number of &
3094 &input layers" &
3095 )
3096 return
3097 end if
3098
3/3
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
7 select type(input)
3099 class is(array_type)
3100
25/46
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✓ Branch 39 taken 3 times.
✓ Branch 40 taken 3 times.
✓ Branch 41 taken 3 times.
✓ Branch 42 taken 3 times.
✓ Branch 43 taken 3 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 3 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 3 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 3 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 3 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 3 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 3 times.
9 allocate(this%input_array(1,size(input,1)))
3101
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
12 do l = 1, size(input,1)
3102
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
6 call handle_array_type(input(l), this%input_array(1,l), num_samples)
3103 end do
3104 type is(array_ptr_type)
3105 2 call stop_program("Use of array_ptr_type with rank 1 input not yet supported")
3106 2 return
3107 ! ip = 0
3108 ! do l = 1, size(input,1)
3109 ! do i = 1, size(input%array,1)
3110 ! ip = ip + 1
3111 ! do j = 1, size(input%array,2)
3112 ! call handle_array_type( &
3113 ! input(l)%array(i,j), this%input_array(ip,j), num_samples &
3114 ! )
3115 ! end do
3116 ! end do
3117 ! end do
3118 end select
3119 rank(2)
3120
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 select type(input)
3121 type is(real(real32))
3122
12/20
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 2 times.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 2 times.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 6 times.
✓ Branch 24 taken 2 times.
14 this%input_array(1,1)%val = reshape(input, [num_inputs, num_samples])
3123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 l_valid_rank_type = .true.
3124 type is(graph_type)
3125 5 num_samples = size(input, dim=2)
3126
31/66
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 5 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 5 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 5 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 5 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 5 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 5 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 5 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 5 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 5 times.
✓ Branch 43 taken 6 times.
✓ Branch 44 taken 5 times.
✓ Branch 45 taken 6 times.
✓ Branch 46 taken 6 times.
✓ Branch 47 taken 6 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 6 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 6 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 6 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 6 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 6 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 6 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 6 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 6 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 6 times.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✓ Branch 72 taken 6 times.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
17 allocate(this%input_graph(num_input_layers, num_samples))
3127
44/104
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 5 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 5 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 5 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 5 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 5 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 5 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 5 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 5 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 5 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 5 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 5 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 5 times.
✓ Branch 54 taken 6 times.
✓ Branch 55 taken 5 times.
✓ Branch 56 taken 6 times.
✓ Branch 57 taken 6 times.
✓ Branch 58 taken 6 times.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✓ Branch 61 taken 6 times.
✗ Branch 62 not taken.
✓ Branch 63 taken 6 times.
✗ Branch 64 not taken.
✓ Branch 65 taken 6 times.
✓ Branch 66 taken 6 times.
✗ Branch 67 not taken.
✓ Branch 68 taken 6 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 6 times.
✗ Branch 71 not taken.
✓ Branch 72 taken 6 times.
✗ Branch 73 not taken.
✓ Branch 74 taken 6 times.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✓ Branch 77 taken 6 times.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✓ Branch 83 taken 6 times.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✓ Branch 88 taken 6 times.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✓ Branch 91 taken 6 times.
✗ Branch 92 not taken.
✓ Branch 93 taken 6 times.
✗ Branch 94 not taken.
✓ Branch 95 taken 6 times.
✗ Branch 96 not taken.
✓ Branch 97 taken 6 times.
✗ Branch 98 not taken.
✓ Branch 99 taken 6 times.
✗ Branch 100 not taken.
✓ Branch 101 taken 6 times.
✗ Branch 102 not taken.
✓ Branch 103 taken 6 times.
✗ Branch 104 not taken.
✓ Branch 105 taken 6 times.
✗ Branch 106 not taken.
✓ Branch 107 taken 6 times.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✓ Branch 115 taken 6 times.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
17 this%input_graph(:,:) = input(:,:)
3128
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
10 return
3129 type is(array_type)
3130 call stop_program("SHOULD NOT GET HERE")
3131 this%input_array = input
3132 l_valid_rank_type = .true.
3133 end select
3134 rank(3)
3135 1 select type(input)
3136 type is(real(real32))
3137
15/30
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 1 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 1 times.
1 call this%input_array(1,1)%set(input)
3138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 l_valid_rank_type = .true.
3139 end select
3140 rank(4)
3141 1 select type(input)
3142 type is(real(real32))
3143
19/38
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 1 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 1 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 1 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 1 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 1 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 1 times.
1 call this%input_array(1,1)%set(input)
3144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 l_valid_rank_type = .true.
3145 end select
3146 rank(5)
3147 1 select type(input)
3148 type is(real(real32))
3149
23/46
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 1 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 1 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 1 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 1 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 1 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 1 times.
✗ Branch 58 not taken.
✓ Branch 59 taken 1 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 1 times.
✗ Branch 64 not taken.
✓ Branch 65 taken 1 times.
✗ Branch 67 not taken.
✓ Branch 68 taken 1 times.
1 call this%input_array(1,1)%set(input)
3150
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 l_valid_rank_type = .true.
3151 end select
3152 end select rank_select
3153
3154
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if(.not.l_valid_rank_type)then
3155 1 write(err_msg,'("Unknown input type for rank ",I0)') input_rank
3156 1 call stop_program(err_msg)
3157 1 return
3158 end if
3159
3160 contains
3161
3162 1230 function get_num_samples(network, input) result(num_samples)
3163 implicit none
3164 !! Get the number of samples in the input
3165
3166 ! Arguments
3167 type(network_type), intent(in) :: network
3168 !! Instance of network
3169 class(*), dimension(..), intent(in) :: input
3170 !! Input
3171 integer :: num_samples
3172 !! Number of samples
3173
3174 ! Local variables
3175 integer :: layer_id
3176 !! Layer ID
3177 logical :: use_graph_input
3178 !! Whether to use graph input
3179
3180 1230 num_samples = 0
3181
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1230 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1230 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1230 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1230 times.
1230 layer_id = network%auto_graph%vertex(network%root_vertices(1))%id
3182
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1230 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1230 times.
1230 use_graph_input = network%model(layer_id)%layer%use_graph_input
3183 select rank(input)
3184 rank(0)
3185
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 select type(input)
3186 class is(array_type)
3187 1 num_samples = size(input%val, 2)
3188 class is(array_ptr_type)
3189
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
1 num_samples = size(input%array(1,1)%val, 2)
3190 class default
3191 1 call stop_program("Unknown input type in get_num_samples for rank 0")
3192 1 return
3193 end select
3194 rank(1)
3195
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 select type(input)
3196 class is(array_type)
3197
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
6 if(use_graph_input)then
3198 2 num_samples = size(input)
3199 else
3200
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 num_samples = size(input(1)%val, 2)
3201 end if
3202 class is(array_ptr_type)
3203
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
4 if(use_graph_input)then
3204
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 num_samples = size(input(1)%array, 2)
3205 else
3206
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
1 num_samples = size(input(1)%array(1,1)%val, 2)
3207 end if
3208 class is(graph_type)
3209 1 num_samples = size(input, dim=1)
3210 type is(real)
3211 1 num_samples = size(input, rank(input))
3212 class default
3213 1 call stop_program("Unknown input type in get_num_samples for rank 1")
3214 1 return
3215 end select
3216 rank(2)
3217
2/2
✓ Branch 0 taken 1211 times.
✓ Branch 1 taken 1 times.
1212 select type(input)
3218 class is(array_type)
3219
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1203 times.
2408 if(use_graph_input)then
3220 1 num_samples = size(input, 2)
3221 else
3222
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1203 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1203 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1203 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1203 times.
1203 num_samples = size(input(1,1)%val, 2)
3223 end if
3224 class is(graph_type)
3225 5 num_samples = size(input, dim=2)
3226 type is(real)
3227 2 num_samples = size(input, rank(input))
3228 class default
3229 1 call stop_program("Unknown input type in get_num_samples for rank 2")
3230 1 return
3231 end select
3232 rank(3)
3233
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 select type(input)
3234 type is(real)
3235 1 num_samples = size(input, rank(input))
3236 class default
3237 1 call stop_program("Unknown input type in get_num_samples for rank 3")
3238 1 return
3239 end select
3240 rank(4)
3241
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 select type(input)
3242 type is(real)
3243 1 num_samples = size(input, rank(input))
3244 class default
3245 1 call stop_program("Unknown input type in get_num_samples for rank 4")
3246 1 return
3247 end select
3248 rank(5)
3249
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 select type(input)
3250 type is(real)
3251 1 num_samples = size(input, rank(input))
3252 class default
3253 1 call stop_program("Unknown input type in get_num_samples for rank 5")
3254 1 return
3255 end select
3256 rank default
3257 1 call stop_program("Unknown input rank in get_num_samples")
3258 1 return
3259 end select
3260
3261 1223 end function get_num_samples
3262
3263
3264 5 subroutine handle_array_type(input, output, num_samples)
3265 !! Handle array type input
3266
3267 ! Arguments
3268 class(array_type), intent(in) :: input
3269 !! Input
3270 type(array_type), intent(out) :: output
3271 !! Output
3272 integer, intent(in) :: num_samples
3273 !! Number of samples
3274
3275
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if(size(input%val,2).ne.num_samples)then
3276 1 call stop_program("number of samples in input arrays do not match")
3277 1 return
3278 end if
3279 call output%allocate( array_shape = &
3280 16 [ product(input%shape(1:input%rank)), num_samples ] &
3281
8/12
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✓ Branch 12 taken 4 times.
✓ Branch 13 taken 4 times.
✓ Branch 14 taken 8 times.
✓ Branch 15 taken 4 times.
16 )
3282
15/36
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 4 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 4 times.
✓ Branch 24 taken 4 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 4 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 4 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 7 times.
✓ Branch 41 taken 4 times.
✓ Branch 42 taken 20 times.
✓ Branch 43 taken 7 times.
31 output%val = input%val
3283 end subroutine handle_array_type
3284
3285 end function save_input_to_network
3286 !-------------------------------------------------------------------------------
3287
1/2
✓ Branch 0 taken 605 times.
✗ Branch 1 not taken.
605 module subroutine save_output_to_network( this, output )
3288 !! Save output to network
3289 implicit none
3290
3291 ! Arguments
3292 class(network_type), intent(inout) :: this
3293 !! Instance of network
3294 class(*), dimension(:,:), intent(in) :: output
3295 !! Output
3296
3297 ! Local variables
3298 integer :: i, j, s
3299 !! Loop indices
3300
3301
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 603 times.
605 if(allocated(this%expected_array))then
3302
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 do i = 1, size(this%expected_array, 1)
3303
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
6 do j = 1, size(this%expected_array, 2)
3304
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
4 call this%expected_array(i,j)%deallocate()
3305 end do
3306 end do
3307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 deallocate(this%expected_array)
3308 end if
3309
3310 select type(output)
3311 type is(graph_type)
3312
25/46
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✓ Branch 39 taken 1 times.
✓ Branch 40 taken 1 times.
✓ Branch 41 taken 2 times.
✓ Branch 42 taken 1 times.
✓ Branch 43 taken 2 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 2 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 2 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 2 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 2 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 2 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 2 times.
4 allocate(this%expected_array(2,size(output,2)))
3313
10/18
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✓ Branch 17 taken 1 times.
3 do s = 1, size(output,2)
3314
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
1 if(this%expected_array(1,s)%allocated) &
3315 call this%expected_array(1,s)%deallocate()
3316
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
1 if(this%expected_array(2,s)%allocated) &
3317 call this%expected_array(2,s)%deallocate()
3318 4 call this%expected_array(1,s)%allocate( &
3319 array_shape = [ &
3320 output(1,s)%num_vertex_features, output(1,s)%num_vertices &
3321 ] &
3322
12/22
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 24 taken 2 times.
✓ Branch 25 taken 1 times.
3 )
3323
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
1 call this%expected_array(1,s)%zero_grad()
3324
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
1 call this%expected_array(1,s)%set_requires_grad(.false.)
3325
18/36
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1 times.
1 call this%expected_array(1,s)%set( output(1,s)%vertex_features )
3326
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
1 this%expected_array(1,s)%is_temporary = .false.
3327
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 if(output(1,s)%num_edge_features.le.0) cycle
3328 call this%expected_array(2,s)%allocate( &
3329 array_shape = [ &
3330 output(1,s)%num_edge_features, output(1,s)%num_edges &
3331 ] &
3332 )
3333 call this%expected_array(2,s)%set_requires_grad(.false.)
3334 call this%expected_array(2,s)%set( output(1,s)%edge_features )
3335
0/8
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
1 this%expected_array(2,s)%is_temporary = .false.
3336 end do
3337 class is(array_type)
3338
27/50
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
✓ Branch 2 taken 604 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 604 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 604 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 604 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 604 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 604 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 604 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 604 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 604 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 604 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 604 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 604 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 604 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 604 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 604 times.
✓ Branch 43 taken 604 times.
✓ Branch 44 taken 604 times.
✓ Branch 45 taken 604 times.
✓ Branch 46 taken 604 times.
✓ Branch 47 taken 604 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 604 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 604 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 604 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 604 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 604 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 604 times.
1812 allocate(this%expected_array(size(output,1),size(output,2)))
3339
10/18
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 604 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 604 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 604 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 604 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 604 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 604 times.
✓ Branch 14 taken 604 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 604 times.
✓ Branch 17 taken 604 times.
2416 do s = 1, size(output,2)
3340
2/2
✓ Branch 0 taken 604 times.
✓ Branch 1 taken 604 times.
1812 do i = 1, size(output,1)
3341
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 604 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 604 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 604 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 604 times.
604 if(this%expected_array(i,s)%allocated) &
3342 call this%expected_array(i,s)%deallocate()
3343 2416 call this%expected_array(i,s)%allocate( &
3344 array_shape = [ &
3345 output(i,s)%shape, size(output(i,s)%val,2) &
3346 ] &
3347
22/40
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 604 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 604 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 604 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 604 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 604 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 604 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 604 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 604 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 604 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 604 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 604 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 604 times.
✓ Branch 35 taken 604 times.
✓ Branch 36 taken 604 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 604 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 604 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 604 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 604 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 604 times.
✓ Branch 47 taken 1208 times.
✓ Branch 48 taken 604 times.
2416 )
3348
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 604 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 604 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 604 times.
604 call this%expected_array(i,s)%set_requires_grad(.false.)
3349
20/40
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 604 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 604 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 604 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 604 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 604 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 604 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 604 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 604 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 604 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 604 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 604 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 604 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 604 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 604 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 604 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 604 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 604 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 604 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 604 times.
604 call this%expected_array(i,s)%set( output(i,s)%val )
3350
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 604 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 604 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 604 times.
1208 this%expected_array(i,s)%is_temporary = .false.
3351 end do
3352 end do
3353 type is(real)
3354 allocate(this%expected_array(1,1))
3355 if(this%expected_array(1,1)%allocated) &
3356 call this%expected_array(1,1)%deallocate()
3357 call this%expected_array(1,1)%allocate( &
3358 array_shape = [ size(output,1), size(output,2) ] &
3359 )
3360 call this%expected_array(1,1)%set_requires_grad(.false.)
3361 call this%expected_array(1,1)%set( output )
3362 this%expected_array(1,1)%is_temporary = .false.
3363 type is(integer)
3364 allocate(this%expected_array(1,1))
3365 if(this%expected_array(1,1)%allocated) &
3366 call this%expected_array(1,1)%deallocate()
3367 call this%expected_array(1,1)%allocate( &
3368 array_shape = [ size(output,1), size(output,2) ] &
3369 )
3370 call this%expected_array(1,1)%set_requires_grad(.false.)
3371 this%expected_array(1,1)%val = real(output, real32)
3372 this%expected_array(1,1)%is_temporary = .false.
3373 class default
3374 call stop_program("output type not supported in training")
3375 end select
3376
3377 605 end subroutine save_output_to_network
3378 !###############################################################################
3379
3380
3381 !##############################################################################!
3382 ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * !
3383 !##############################################################################!
3384
3385
3386 !###############################################################################
3387 5 module subroutine train( &
3388
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 this, input, output, num_epochs, batch_size, &
3389 plateau_threshold, shuffle_batches, batch_print_step, verbose, &
3390 print_precision, scientific_print, early_stopping, &
3391
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
5 val_input, val_output &
3392 )
3393 !! Train the network
3394 !!
3395 !! This function trains the network on the input data for a number of
3396 !! epochs. The input data is split into batches of size batch_size and
3397 !! the network is trained on each batch. The network is trained using
3398 !! the optimiser specified in the network object.
3399 use athena__tools_infile, only: stop_check
3400 implicit none
3401
3402 ! Arguments
3403 class(network_type), intent(inout) :: this
3404 !! Instance of network
3405 class(*), dimension(..), intent(in) :: input
3406 !! Input data
3407 class(*), dimension(:,:), intent(in) :: output
3408 !! Output data
3409 integer, intent(in) :: num_epochs
3410 !! Number of epochs
3411 integer, optional, intent(in) :: batch_size
3412 !! Batch size
3413 real(real32), optional, intent(in) :: plateau_threshold
3414 !! Plateau threshold
3415 logical, optional, intent(in) :: shuffle_batches
3416 !! Shuffle batches
3417 integer, optional, intent(in) :: batch_print_step
3418 !! Batch print step
3419 integer, optional, intent(in) :: verbose
3420 !! Verbosity level
3421 integer, optional, intent(in) :: print_precision
3422 !! Number of decimal places to print for training metrics
3423 logical, optional, intent(in) :: scientific_print
3424 !! Whether to print training metrics in scientific notation
3425 logical, optional, intent(in) :: early_stopping
3426 !! Whether to stop training early if convergence is detected
3427 class(*), dimension(..), optional, intent(in) :: val_input
3428 !! Validation input data
3429 class(*), dimension(:,:), optional, intent(in) :: val_output
3430 !! Validation expected output data
3431
3432 ! Training parameters
3433 real(real32) :: batch_loss, batch_accuracy, avg_loss, avg_accuracy
3434 !! Loss and accuracy
3435
3436 ! learning parameters
3437 integer :: l, num_samples
3438 !! Loop index
3439 integer :: num_batches
3440 !! Number of batches
3441 integer :: converged
3442 !! Convergence flag
3443 integer :: window_width
3444 !! Length of convergence check window
3445 integer :: verbose_
3446 !! Verbosity level
3447 real(real32) :: plateau_threshold_
3448 !! Plateau threshold
3449 logical :: shuffle_batches_
3450 !! Shuffle batches
3451 logical :: use_accuracy
3452 !! Whether accuracy evaluation is available
3453 logical :: early_stopping_
3454 !! Whether to stop training early if convergence is detected
3455
3456 ! Printing parameters
3457 integer :: batch_print_step_
3458 !! Batch print step
3459 integer :: print_precision_
3460 !! Number of decimal places for metric output
3461 logical :: scientific_print_
3462 !! Whether to print metrics in scientific notation
3463 character(len=64) :: loss_str, accuracy_str
3464 !! Formatted metrics for printing
3465 character(len=128) :: val_str
3466 !! Formatted validation metrics for printing
3467
3468 ! Training loop variables
3469 integer :: epoch, batch, start_index, end_index
3470 !! Loop index
3471 5 integer, allocatable, dimension(:) :: batch_order
3472 !! Batch order
3473
3474 integer :: i, j, s
3475 !! Loop index
3476 integer :: tmp_batch_size
3477 !! Temporary integer to store batch size during validation
3478 integer :: current_batch_size, target_batch_size
3479 !! Actual batch size for the current batch and the target batch size
3480 5 logical, allocatable :: mode_store(:)
3481 !! Storage for inference mode booleans
3482
3483 10 class(*), allocatable :: data_poly(:,:)
3484 type(array_type), pointer :: loss => null()
3485
3486 ! Validation variables
3487 logical :: use_validation
3488 !! Whether validation data is provided
3489 integer :: val_num_samples
3490 !! Number of validation samples
3491 integer :: val_sample
3492 !! Loop index for validation
3493 real(real32) :: val_loss, val_accuracy, val_loss_sum, val_accuracy_sum
3494 !! Validation loss and accuracy
3495 #ifdef __INTEL_COMPILER
3496 type(array_type), pointer :: saved_expected_array(:,:) => null()
3497 !! Saved training expected output (for restoring after validation)
3498 #else
3499 5 type(array_type), dimension(:,:), allocatable :: saved_expected_array
3500 !! Saved training expected output (for restoring after validation)
3501 #endif
3502
3503 #ifdef _OPENMP
3504 type(network_type) :: this_copy
3505 !! Copy of network
3506 #endif
3507
3508
3509 !---------------------------------------------------------------------------
3510 ! Check loss and accuracy methods are set
3511 !---------------------------------------------------------------------------
3512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(.not.allocated(this%loss))then
3513 call stop_program("loss method not set")
3514 return
3515 end if
3516 5 use_accuracy = associated(this%get_accuracy)
3517 5 accuracy_str = ""
3518 5 val_str = ""
3519
3520 !---------------------------------------------------------------------------
3521 ! Check validation data
3522 !---------------------------------------------------------------------------
3523
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
5 use_validation = present(val_input) .and. present(val_output)
3524
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
5 if(present(val_input) .neqv. present(val_output))then
3525 call stop_program( &
3526 "both val_input and val_output must be provided for validation" &
3527 )
3528 return
3529 end if
3530
3531
3532 !---------------------------------------------------------------------------
3533 ! Initialise optional arguments
3534 !---------------------------------------------------------------------------
3535 5 verbose_ = 0
3536 5 batch_print_step_ = 20
3537 5 plateau_threshold_ = 0._real32
3538 5 shuffle_batches_ = .true.
3539 5 scientific_print_ = .false.
3540 5 print_precision_ = 3
3541 5 early_stopping_ = .true.
3542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(present(plateau_threshold)) plateau_threshold_ = plateau_threshold
3543
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if(present(shuffle_batches)) shuffle_batches_ = shuffle_batches
3544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(present(batch_print_step)) batch_print_step_ = batch_print_step
3545
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if(present(verbose)) verbose_ = verbose
3546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(present(print_precision)) print_precision_ = max(print_precision, 0)
3547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if(present(scientific_print)) scientific_print_ = scientific_print
3548
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if(present(batch_size)) this%batch_size = batch_size
3549
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if(present(early_stopping)) early_stopping_ = early_stopping
3550
3551
3552 !---------------------------------------------------------------------------
3553 ! Initialise monitoring variables
3554 !---------------------------------------------------------------------------
3555
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 window_width = max(ceiling(500._real32/this%batch_size),1)
3556
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 5 times.
15 do i = 1, size(this%metrics,dim=1)
3557
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
15 this%metrics(i)%window_width = window_width
3558 end do
3559
3560
3561 !---------------------------------------------------------------------------
3562 ! Save input and output to network
3563 !---------------------------------------------------------------------------
3564 5 num_samples = this%save_input( input )
3565
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 5 times.
5 call this%save_output( output )
3566
8/16
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 5 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 5 times.
5 if(size(output,2).ne.num_samples.and.this%use_graph_output)then
3567 call stop_program("number of samples in input and output do not match")
3568 return
3569 end if
3570
3571
3572 !---------------------------------------------------------------------------
3573 ! If parallel, initialise slices
3574 !---------------------------------------------------------------------------
3575 5 num_batches = (num_samples + this%batch_size - 1) / this%batch_size
3576
7/14
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 5 times.
5 allocate(batch_order(num_batches))
3577
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 do batch = 1, num_batches
3578
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
11 batch_order(batch) = batch
3579 end do
3580
3581
3582 !---------------------------------------------------------------------------
3583 ! Set/reset batch size for training
3584 !---------------------------------------------------------------------------
3585 5 call this%set_batch_size(this%batch_size)
3586 5 target_batch_size = this%batch_size
3587
3588
3589 !---------------------------------------------------------------------------
3590 ! Enable training mode
3591 !---------------------------------------------------------------------------
3592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 call this%set_training_mode(mode_store)
3593
3594
3595
2/2
✓ Branch 0 taken 1111 times.
✓ Branch 1 taken 4 times.
1115 epoch_loop: do epoch = 1, num_epochs
3596 1111 this%epoch = epoch
3597 !------------------------------------------------------------------------
3598 ! Shuffle batch order at the start of each epoch
3599 !------------------------------------------------------------------------
3600
2/2
✓ Branch 0 taken 1101 times.
✓ Branch 1 taken 10 times.
1111 if(shuffle_batches_)then
3601 1101 call shuffle(batch_order)
3602 end if
3603
3604 1111 avg_loss = 0._real32
3605 1111 avg_accuracy = 0._real32
3606
3607 !------------------------------------------------------------------------
3608 ! Batch loop
3609 ! ... split data up into minibatches for training
3610 !------------------------------------------------------------------------
3611
2/2
✓ Branch 0 taken 1112 times.
✓ Branch 1 taken 1111 times.
2223 batch_loop: do batch = 1, num_batches
3612
3613
3614 ! Set batch start and end index
3615 !---------------------------------------------------------------------
3616
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1112 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1112 times.
1112 start_index = (batch_order(batch) - 1) * this%batch_size + 1
3617
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1112 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1112 times.
1112 end_index = min(batch_order(batch) * this%batch_size, num_samples)
3618 1112 current_batch_size = end_index - start_index + 1
3619
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1111 times.
1112 if(current_batch_size.ne.target_batch_size)then
3620 1 call this%set_batch_size(current_batch_size)
3621 end if
3622
3623
3624 ! Forward pass
3625 !---------------------------------------------------------------------
3626 1112 select case(this%use_graph_input)
3627 case(.true.)
3628 data_poly = get_sample( &
3629 this%input_graph, start_index, end_index, current_batch_size &
3630
11/32
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 10 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 10 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 10 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 10 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 10 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 10 times.
✗ Branch 25 not taken.
✗ Branch 27 not taken.
✓ Branch 28 taken 10 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
10 )
3631 case default
3632 data_poly = get_sample( &
3633 this%input_array, start_index, end_index, current_batch_size, &
3634 as_graph = .false. &
3635
26/54
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1102 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1102 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 10 taken 1102 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1102 times.
✓ Branch 13 taken 1102 times.
✓ Branch 14 taken 1102 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1102 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1102 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 1102 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1102 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1102 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 1102 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 1102 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 1102 times.
✓ Branch 37 taken 1102 times.
✓ Branch 38 taken 1102 times.
✓ Branch 39 taken 1102 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 1102 times.
✓ Branch 43 taken 1102 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 1102 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 1102 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 1102 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 1102 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 1102 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 1102 times.
5520 )
3636 end select
3637 1112 call this%forward(data_poly)
3638
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1112 times.
✓ Branch 3 taken 1112 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1112 times.
✗ Branch 6 not taken.
1112 deallocate(data_poly)
3639
3640
3641 ! Backward pass
3642 !---------------------------------------------------------------------
3643 1112 loss => this%loss_eval(start_index, end_index)
3644 1112 loss%is_temporary = .false.
3645 1112 call loss%grad_reverse(reset_graph=.true.)
3646
3647
3648 ! Compute loss and accuracy (for monitoring)
3649 !---------------------------------------------------------------------
3650
12/20
✗ Branch 0 not taken.
✓ Branch 1 taken 1112 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1112 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1112 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1112 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1112 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1112 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1112 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1112 times.
✓ Branch 24 taken 1112 times.
✓ Branch 25 taken 1112 times.
✓ Branch 26 taken 1112 times.
✓ Branch 27 taken 1112 times.
3336 batch_loss = sum(loss%val)
3651 1112 batch_accuracy = 0._real32
3652
1/2
✓ Branch 0 taken 1112 times.
✗ Branch 1 not taken.
1112 if(use_accuracy)then
3653
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 1112 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1112 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1112 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1112 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1112 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1112 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1112 times.
1112 batch_accuracy = this%accuracy_eval(output, start_index, end_index)
3654 end if
3655
3656
3657 ! Average metric over batch size and store
3658 !---------------------------------------------------------------------
3659 1112 avg_loss = avg_loss + batch_loss
3660
1/2
✓ Branch 0 taken 1112 times.
✗ Branch 1 not taken.
1112 if(use_accuracy)then
3661 1112 avg_accuracy = avg_accuracy + batch_accuracy
3662 end if
3663
3664
3665 ! Update weights and biases using optimisation algorithm
3666 !---------------------------------------------------------------------
3667 1112 call this%update()
3668 1112 call loss%nullify_graph()
3669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1112 times.
1112 deallocate(loss)
3670 1112 nullify(loss)
3671
3672
3673 ! Print batch results
3674 !---------------------------------------------------------------------
3675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1112 times.
1112 if(abs(verbose_).gt.0.and.&
3676 (batch.eq.1.or.abs(mod(batch,batch_print_step_)).lt.1.E-6))then
3677 loss_str = format_training_real( &
3678 avg_loss / real(batch, real32), print_precision_, &
3679 scientific_print_ &
3680 )
3681 if(use_accuracy)then
3682 accuracy_str = ", accuracy=" // trim(format_training_real( &
3683 avg_accuracy / real(batch, real32), &
3684 print_precision_, scientific_print_ &
3685 ))
3686 end if
3687
3688 write(6,'("epoch=",I0,", batch=",I0,&
3689 &", lr=",ES0.2,", loss=",A,A)' &
3690 ) &
3691 this%epoch, batch, &
3692 this%optimiser%lr_decay%get_lr( &
3693 this%optimiser%learning_rate, this%optimiser%iter &
3694 ), &
3695 trim(loss_str), trim(accuracy_str)
3696 end if
3697
3698
3699 ! Check for user-name stop file
3700 !---------------------------------------------------------------------
3701
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1112 times.
2223 if(stop_check())then
3702 write(0,*) "STOPCAR ENCOUNTERED"
3703 write(0,*) "Exiting training loop..."
3704 exit epoch_loop
3705 end if
3706
3707 end do batch_loop
3708 1111 call this%metrics(1)%append(avg_loss / real(num_batches, real32))
3709
1/2
✓ Branch 0 taken 1111 times.
✗ Branch 1 not taken.
1111 if(use_accuracy)then
3710 1111 call this%metrics(2)%append(avg_accuracy / real(num_batches, real32))
3711 end if
3712
3713
3714 !------------------------------------------------------------------------
3715 ! Validation evaluation at end of epoch
3716 !------------------------------------------------------------------------
3717 1111 val_str = ""
3718
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 511 times.
1111 if(use_validation)then
3719
3720 #ifdef __INTEL_COMPILER
3721 ! Save training expected output. `ifx` crashes on the allocatable
3722 ! local declaration used with `move_alloc`, so keep an explicit
3723 ! pointer-backed copy here instead.
3724 if(allocated(this%expected_array))then
3725 allocate(saved_expected_array( &
3726 size(this%expected_array, 1), size(this%expected_array, 2) &
3727 ))
3728 do i = 1, size(this%expected_array, 1)
3729 do j = 1, size(this%expected_array, 2)
3730 call saved_expected_array(i,j)%allocate( &
3731 source=this%expected_array(i,j) &
3732 )
3733 call this%expected_array(i,j)%deallocate()
3734 end do
3735 end do
3736 deallocate(this%expected_array)
3737 else
3738 nullify(saved_expected_array)
3739 end if
3740 #else
3741
2/18
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 600 times.
600 call move_alloc(this%expected_array, saved_expected_array)
3742 #endif
3743
3744 ! Save validation output to network
3745
9/18
✓ Branch 0 taken 600 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 600 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 600 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 600 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 600 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 600 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 600 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 600 times.
✓ Branch 22 taken 600 times.
✗ Branch 23 not taken.
600 call this%save_output( val_output )
3746
3747 ! Save validation input
3748 600 val_num_samples = this%save_input( val_input )
3749
3750 ! Set batch size to 1 and enable inference mode
3751 600 call this%set_batch_size(1)
3752 600 call this%set_inference_mode()
3753
3754 ! Evaluate validation loss and accuracy
3755 600 val_loss_sum = 0._real32
3756 600 val_accuracy_sum = 0._real32
3757
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 600 times.
1200 do val_sample = 1, val_num_samples
3758 600 select case(this%use_graph_input)
3759 case(.true.)
3760 data_poly = get_sample( &
3761 this%input_graph, val_sample, val_sample, 1 &
3762 )
3763 case default
3764 data_poly = get_sample_array( &
3765 this%input_array, val_sample, val_sample, 1, &
3766 as_graph = .false. &
3767
25/54
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 600 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 10 taken 600 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 600 times.
✓ Branch 13 taken 600 times.
✓ Branch 14 taken 600 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 600 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 600 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 600 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 600 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 600 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 600 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 600 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 600 times.
✓ Branch 37 taken 600 times.
✓ Branch 38 taken 600 times.
✓ Branch 39 taken 600 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 600 times.
✓ Branch 43 taken 600 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 600 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 600 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 600 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 600 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 600 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 600 times.
3000 )
3768 end select
3769 600 call this%forward(data_poly)
3770
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
✓ Branch 3 taken 600 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 600 times.
✗ Branch 6 not taken.
600 deallocate(data_poly)
3771
3772 600 loss => this%loss_eval(val_sample, val_sample)
3773
12/20
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 600 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 600 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 600 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 600 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 600 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 600 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 600 times.
✓ Branch 24 taken 600 times.
✓ Branch 25 taken 600 times.
✓ Branch 26 taken 600 times.
✓ Branch 27 taken 600 times.
1800 val_loss_sum = val_loss_sum + sum(loss%val)
3774 600 call loss%nullify_graph()
3775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
600 deallocate(loss)
3776 600 nullify(loss)
3777
3778
1/2
✓ Branch 0 taken 600 times.
✗ Branch 1 not taken.
1200 if(use_accuracy)then
3779 val_accuracy_sum = val_accuracy_sum + &
3780
9/18
✓ Branch 0 taken 600 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 600 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 600 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 600 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 600 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 600 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 600 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 600 times.
✓ Branch 22 taken 600 times.
✗ Branch 23 not taken.
600 this%accuracy_eval(val_output, val_sample, val_sample)
3781 end if
3782 end do
3783
3784 600 val_loss = val_loss_sum / real(val_num_samples, real32)
3785 600 val_accuracy = val_accuracy_sum / real(val_num_samples, real32)
3786
3787 ! Build validation print string
3788 val_str = ", val_loss=" // trim(format_training_real( &
3789 val_loss, print_precision_, scientific_print_ &
3790
2/4
✓ Branch 3 taken 600 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 600 times.
✗ Branch 6 not taken.
600 ))
3791
1/2
✓ Branch 0 taken 600 times.
✗ Branch 1 not taken.
600 if(use_accuracy)then
3792 val_str = trim(val_str) // ", val_accuracy=" // &
3793 trim(format_training_real( &
3794 val_accuracy, print_precision_, scientific_print_ &
3795
3/6
✓ Branch 2 taken 600 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 600 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 600 times.
✗ Branch 10 not taken.
600 ))
3796 end if
3797
3798 ! Restore training expected output
3799
1/2
✓ Branch 0 taken 600 times.
✗ Branch 1 not taken.
600 if(allocated(this%expected_array))then
3800
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 600 times.
1200 do i = 1, size(this%expected_array, 1)
3801
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 600 times.
1800 do j = 1, size(this%expected_array, 2)
3802
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 600 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 600 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 600 times.
1200 call this%expected_array(i,j)%deallocate()
3803 end do
3804 end do
3805
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
600 deallocate(this%expected_array)
3806 end if
3807 #ifdef __INTEL_COMPILER
3808 ! `ifx` does not support `move_alloc` in this context
3809 if(associated(saved_expected_array))then
3810 allocate(this%expected_array( &
3811 size(saved_expected_array, 1), size(saved_expected_array, 2) &
3812 ))
3813 do i = 1, size(saved_expected_array, 1)
3814 do j = 1, size(saved_expected_array, 2)
3815 call this%expected_array(i,j)%allocate( &
3816 source=saved_expected_array(i,j) &
3817 )
3818 call saved_expected_array(i,j)%deallocate()
3819 end do
3820 end do
3821 deallocate(saved_expected_array)
3822 nullify(saved_expected_array)
3823 end if
3824 #else
3825
2/18
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 600 times.
600 call move_alloc(saved_expected_array, this%expected_array)
3826 #endif
3827
3828 ! Restore training input
3829 600 num_samples = this%save_input( input )
3830
3831 ! Restore training batch size and inference mode
3832 600 call this%set_batch_size(target_batch_size)
3833 600 call this%set_training_mode()
3834
3835 end if
3836
3837
3838 ! Print epoch summary results
3839 !------------------------------------------------------------------------
3840
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 511 times.
1111 if(use_validation.and.verbose_.ge.0)then
3841
1/2
✓ Branch 4 taken 600 times.
✗ Branch 5 not taken.
600 write(6,'("epoch=",I0,A)') this%epoch, trim(val_str)
3842
1/2
✓ Branch 0 taken 511 times.
✗ Branch 1 not taken.
511 elseif(verbose_.eq.0)then
3843 loss_str = format_training_real( &
3844 this%metrics(1)%val, print_precision_, scientific_print_ &
3845 511 )
3846
1/2
✓ Branch 0 taken 511 times.
✗ Branch 1 not taken.
511 if(use_accuracy)then
3847 accuracy_str = ", accuracy=" // trim(format_training_real( &
3848 this%metrics(2)%val, print_precision_, scientific_print_ &
3849
2/4
✓ Branch 3 taken 511 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 511 times.
✗ Branch 6 not taken.
511 ))
3850 end if
3851 write(6,'("epoch=",I0,&
3852 &", lr=",ES0.2,", loss=",A,A,A)' &
3853 ) &
3854 511 this%epoch, &
3855 this%optimiser%lr_decay%get_lr( &
3856 this%optimiser%learning_rate, this%optimiser%iter &
3857 511 ), &
3858
3/6
✓ Branch 3 taken 511 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 511 times.
✗ Branch 8 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 511 times.
1022 trim(loss_str), trim(accuracy_str), trim(val_str)
3859 end if
3860
3861
3862 !------------------------------------------------------------------------
3863 ! Per-epoch callback (e.g. W&B logging via wandb_network_type)
3864 !------------------------------------------------------------------------
3865 call this%post_epoch_hook( &
3866 this%epoch, &
3867 this%metrics(1)%val, &
3868 this%metrics(2)%val &
3869 1111 )
3870
3871 !------------------------------------------------------------------------
3872 ! Check for convergence and stop early if enabled
3873 ! When validation data is provided, check validation loss for plateau
3874 !------------------------------------------------------------------------
3875
2/2
✓ Branch 0 taken 1110 times.
✓ Branch 1 taken 1 times.
1115 if(early_stopping_)then
3876
2/2
✓ Branch 0 taken 600 times.
✓ Branch 1 taken 510 times.
1110 if(use_validation)then
3877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 600 times.
600 if(val_loss .lt. plateau_threshold_ .and. &
3878 plateau_threshold_ .gt. 0._real32) exit epoch_loop
3879 else
3880 510 call this%metrics(1)%check(plateau_threshold_, converged)
3881
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 509 times.
510 if(converged.ne.0) exit epoch_loop
3882 end if
3883
1/2
✓ Branch 0 taken 1109 times.
✗ Branch 1 not taken.
1109 if(use_accuracy)then
3884 1109 call this%metrics(2)%check(plateau_threshold_, converged)
3885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1109 times.
1109 if(converged.ne.0) exit epoch_loop
3886 end if
3887 end if
3888
3889 end do epoch_loop
3890
3891 ! Final epoch metrics
3892
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if(use_accuracy)then
3893 5 this%accuracy_val = this%metrics(2)%val
3894 else
3895 this%accuracy_val = 0._real32
3896 end if
3897 5 this%loss_val = this%metrics(1)%val
3898
3899
3900 !---------------------------------------------------------------------------
3901 ! Restore training/inference mode
3902 !---------------------------------------------------------------------------
3903 5 call this%restore_mode(mode_store)
3904
3905
4/12
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
5 end subroutine train
3906 !###############################################################################
3907
3908
3909 !###############################################################################
3910 2222 function format_training_real(value, decimals, scientific) result(formatted)
3911 !! Format a training metric with a configurable number of decimal places.
3912 implicit none
3913
3914 ! Arguments
3915 real(real32), intent(in) :: value
3916 !! Value to format
3917 integer, intent(in) :: decimals
3918 !! Number of decimal places
3919 logical, intent(in) :: scientific
3920 !! Whether to use scientific notation
3921
3922 character(len=64) :: formatted
3923 !! Formatted string
3924
3925 ! Local variables
3926 character(len=16) :: fmt
3927 !! Internal write format
3928 integer :: width_
3929 !! Field width for scientific formatting
3930 integer :: decimals_
3931 !! Clamped decimal count
3932
3933 2222 decimals_ = min(max(decimals, 0), 30)
3934
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2222 times.
2222 if(scientific)then
3935 width_ = max(decimals_ + 8, 14)
3936 write(fmt,'("(ES",I0,".",I0,"E2)")') width_, decimals_
3937 else
3938 2222 write(fmt,'("(F0.",I0,")")') decimals_
3939 end if
3940 2222 write(formatted, fmt) value
3941 2222 formatted = adjustl(formatted)
3942
3943 2222 end function format_training_real
3944 !###############################################################################
3945
3946
3947 !###############################################################################
3948 4 module subroutine test( &
3949
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 this, input, output, verbose &
3950 )
3951 !! Test the network
3952 implicit none
3953
3954 ! Arguments
3955 class(network_type), intent(inout) :: this
3956 !! Instance of network
3957 class(*), dimension(..), intent(in) :: input
3958 !! Input data
3959 class(*), dimension(:,:), intent(in) :: output
3960 !! Output data
3961 integer, optional, intent(in) :: verbose
3962 !! Verbosity level
3963
3964 ! Local variables
3965 integer :: l, sample, num_samples
3966 !! Loop index
3967 integer :: verbose_
3968 !! Verbosity level
3969 logical :: use_accuracy
3970 !! Whether accuracy evaluation is available
3971 real(real32) :: acc_val, loss_val
3972 !! Loss and accuracy
3973 8 class(*), allocatable, dimension(:,:) :: data_poly
3974 !! Polymorphic data array
3975 type(array_type), pointer :: loss => null()
3976 !! Loss
3977 4 logical, allocatable :: mode_store(:)
3978 !! Storage for inference mode booleans
3979
3980
3981 !---------------------------------------------------------------------------
3982 ! Initialise optional arguments
3983 !---------------------------------------------------------------------------
3984
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(present(verbose))then
3985 verbose_ = verbose
3986 else
3987 4 verbose_ = 0
3988 end if
3989 4 use_accuracy = associated(this%get_accuracy)
3990
3991
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 do l = 1, size(this%metrics,dim=1)
3992
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
12 this%metrics(l)%val = 0._real32
3993 end do
3994 4 loss_val = 0._real32
3995 4 acc_val = 0._real32
3996
3997
3998 4 num_samples = this%save_input( input )
3999
4000
4001 !---------------------------------------------------------------------------
4002 ! Reset batch size for testing
4003 !---------------------------------------------------------------------------
4004 4 call this%set_batch_size(1)
4005
4006
4007 !---------------------------------------------------------------------------
4008 ! Enable inference mode
4009 !---------------------------------------------------------------------------
4010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 call this%set_inference_mode(mode_store)
4011
4012
4013 !---------------------------------------------------------------------------
4014 ! Testing loop
4015 !---------------------------------------------------------------------------
4016
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 test_loop1: do sample = 1, num_samples
4017
4018 ! Forward pass
4019 !------------------------------------------------------------------------
4020 4 select case(this%use_graph_input)
4021 case(.true.)
4022 data_poly = get_sample( &
4023 this%input_graph, sample, sample, 1 &
4024
11/32
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 2 times.
✗ Branch 25 not taken.
✗ Branch 27 not taken.
✓ Branch 28 taken 2 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
2 )
4025 case default
4026 data_poly = get_sample_array( &
4027 this%input_array, sample, sample, 1, &
4028 as_graph = .false. &
4029
26/54
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 2 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 2 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 2 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 2 times.
✓ Branch 37 taken 2 times.
✓ Branch 38 taken 2 times.
✓ Branch 39 taken 2 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 2 times.
✓ Branch 43 taken 2 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 2 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 2 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 2 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 2 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 2 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 2 times.
12 )
4030 end select
4031 4 call this%forward(data_poly)
4032
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 deallocate(data_poly)
4033
4034
4035 ! Compute loss and accuracy (for monitoring)
4036 !------------------------------------------------------------------------
4037 4 loss => this%loss_eval(sample, sample)
4038
12/20
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 4 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 4 times.
✓ Branch 24 taken 4 times.
✓ Branch 25 taken 4 times.
✓ Branch 26 taken 4 times.
✓ Branch 27 taken 4 times.
12 loss_val = sum(loss%val)
4039 4 call loss%nullify_graph()
4040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 deallocate(loss)
4041 4 nullify(loss)
4042
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if(use_accuracy)then
4043
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 4 times.
4 acc_val = this%accuracy_eval(output, sample, sample)
4044 4 this%metrics(2)%val = this%metrics(2)%val + acc_val
4045 end if
4046 8 this%metrics(1)%val = this%metrics(1)%val + loss_val
4047
4048 end do test_loop1
4049
4050
4051 ! Normalise metrics by number of samples
4052 !---------------------------------------------------------------------------
4053
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if(use_accuracy)then
4054 4 this%accuracy_val = this%metrics(2)%val / real(num_samples, real32)
4055 else
4056 this%accuracy_val = 0._real32
4057 end if
4058 4 this%loss_val = this%metrics(1)%val / real(num_samples, real32)
4059
4060
4061 !---------------------------------------------------------------------------
4062 ! Restore training/inference mode
4063 !---------------------------------------------------------------------------
4064 4 call this%restore_mode(mode_store)
4065
4066
2/8
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
4 end subroutine test
4067 !###############################################################################
4068
4069
4070 !###############################################################################
4071 13 module function predict_real( &
4072 this, input, verbose &
4073 ) result(output)
4074 !! Predict the output for a 1D input
4075 implicit none
4076
4077 ! Arguments
4078 class(network_type), intent(inout) :: this
4079 !! Instance of network
4080 real(real32), dimension(..), intent(in) :: input
4081 !! Input
4082 integer, optional, intent(in) :: verbose
4083 !! Verbosity level
4084
4085 ! Local variables
4086 real(real32), dimension(:,:), allocatable :: output
4087 !! Output
4088 integer :: verbose_, batch_size
4089 !! Verbosity level
4090 13 logical, allocatable :: mode_store(:)
4091 !! Storage for inference mode booleans
4092
4093
4094 !---------------------------------------------------------------------------
4095 ! Initialise optional arguments
4096 !---------------------------------------------------------------------------
4097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if(present(verbose))then
4098 verbose_ = verbose
4099 else
4100 13 verbose_ = 0
4101 end if
4102
4103 select rank(input)
4104 rank(2)
4105 13 batch_size = size(input,dim=2)
4106 rank(3)
4107 batch_size = size(input,dim=3)
4108 rank(4)
4109 batch_size = size(input,dim=4)
4110 rank(5)
4111 batch_size = size(input,dim=5)
4112 rank(6)
4113 batch_size = size(input,dim=6)
4114 rank default
4115 batch_size = size(input,dim=rank(input))
4116 end select
4117
4118
4119 !---------------------------------------------------------------------------
4120 ! Reset batch size for testing
4121 !---------------------------------------------------------------------------
4122 13 call this%set_batch_size(batch_size)
4123
4124
4125 !---------------------------------------------------------------------------
4126 ! Enable inference mode
4127 !---------------------------------------------------------------------------
4128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 call this%set_inference_mode(mode_store)
4129
4130
4131 !---------------------------------------------------------------------------
4132 ! Predict
4133 !---------------------------------------------------------------------------
4134 13 call this%forward(get_sample(input, 1, batch_size, batch_size))
4135
4136
27/54
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 13 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 13 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 13 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 13 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 13 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 13 times.
✗ Branch 26 not taken.
✓ Branch 27 taken 13 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 13 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 13 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 13 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 13 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 13 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 13 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 13 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 13 times.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✓ Branch 56 taken 13 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 13 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 13 times.
✗ Branch 61 not taken.
✓ Branch 62 taken 13 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 13 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 35 times.
✓ Branch 67 taken 13 times.
✓ Branch 68 taken 404 times.
✓ Branch 69 taken 35 times.
452 output = this%model(this%leaf_vertices(1))%layer%output(1,1)%val
4137
4138
4139 !---------------------------------------------------------------------------
4140 ! Restore training/inference mode
4141 !---------------------------------------------------------------------------
4142 13 call this%restore_mode(mode_store)
4143
4144
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 end function predict_real
4145 !###############################################################################
4146
4147
4148 !###############################################################################
4149 module function predict_graph1d( this, input, verbose ) result(output)
4150 !! Predict the output for a graph input
4151 implicit none
4152
4153 ! Arguments
4154 class(network_type), intent(inout) :: this
4155 !! Instance of network
4156 type(graph_type), dimension(:), intent(in) :: input
4157 !! Input graph
4158 integer, optional, intent(in) :: verbose
4159 !! Verbosity level
4160
4161 ! Local variables
4162 integer :: l, s
4163 !! Loop index
4164 type(graph_type), dimension(size(this%leaf_vertices),size(input)) :: output
4165 !! Output graph
4166 integer :: verbose_ = 0, batch_size
4167 !! Verbosity level
4168 logical, allocatable :: mode_store(:)
4169 !! Storage for inference mode booleans
4170
4171
4172 !---------------------------------------------------------------------------
4173 ! Initialise optional arguments
4174 !---------------------------------------------------------------------------
4175 if(present(verbose)) verbose_ = verbose
4176
4177 !---------------------------------------------------------------------------
4178 ! Reset batch size for testing
4179 !---------------------------------------------------------------------------
4180 batch_size = size(input)
4181 call this%set_batch_size(batch_size)
4182
4183
4184 !---------------------------------------------------------------------------
4185 ! Enable inference mode
4186 !---------------------------------------------------------------------------
4187 call this%set_inference_mode(mode_store)
4188
4189
4190 !---------------------------------------------------------------------------
4191 ! Predict
4192 !---------------------------------------------------------------------------
4193 call this%forward(get_sample(input, 1, batch_size, batch_size))
4194
4195 do l = 1, size(this%leaf_vertices)
4196 do s = 1, batch_size
4197 output(l,s)%num_vertices = input(s)%num_vertices
4198 output(l,s)%num_edges = input(s)%num_edges
4199 output(l,s)%num_vertex_features = this%model( &
4200 this%leaf_vertices(l) &
4201 )%layer%output_shape(1)
4202 output(l,s)%num_edge_features = this%model( &
4203 this%leaf_vertices(l) &
4204 )%layer%output_shape(2)
4205 output(l,s)%vertex_features = this%model( &
4206 this%leaf_vertices(l) &
4207 )%layer%output(1,s)%val
4208 if(size(this%model(this%leaf_vertices(l))%layer%output,1).eq.1)then
4209 output(l,s)%edge_features = input(s)%edge_features
4210 else
4211 output(l,s)%edge_features = this%model( &
4212 this%leaf_vertices(l) &
4213 )%layer%output(2,s)%val
4214 end if
4215 end do
4216 end do
4217
4218
4219 !---------------------------------------------------------------------------
4220 ! Restore training/inference mode
4221 !---------------------------------------------------------------------------
4222 call this%restore_mode(mode_store)
4223
4224 end function predict_graph1d
4225 !-------------------------------------------------------------------------------
4226 module function predict_graph2d( this, input, verbose ) result(output)
4227 !! Predict the output for a graph input
4228 implicit none
4229
4230 ! Arguments
4231 class(network_type), intent(inout) :: this
4232 !! Instance of network
4233 type(graph_type), dimension(:,:), intent(in) :: input
4234 !! Input graph
4235 integer, optional, intent(in) :: verbose
4236 !! Verbosity level
4237
4238 ! Local variables
4239 integer :: l, s
4240 !! Loop index
4241 type(graph_type), dimension(size(this%leaf_vertices),size(input,dim=2)) :: &
4242 output
4243 !! Output graph
4244 integer :: verbose_ = 0, batch_size
4245 !! Verbosity level
4246 logical, allocatable :: mode_store(:)
4247 !! Storage for inference mode booleans
4248
4249
4250 !---------------------------------------------------------------------------
4251 ! Initialise optional arguments
4252 !---------------------------------------------------------------------------
4253 if(present(verbose)) verbose_ = verbose
4254
4255 !---------------------------------------------------------------------------
4256 ! Reset batch size for testing
4257 !---------------------------------------------------------------------------
4258 batch_size = size(input, 2)
4259 call this%set_batch_size(batch_size)
4260
4261
4262 !---------------------------------------------------------------------------
4263 ! Enable inference mode
4264 !---------------------------------------------------------------------------
4265 call this%set_inference_mode(mode_store)
4266
4267
4268 !---------------------------------------------------------------------------
4269 ! Predict
4270 !---------------------------------------------------------------------------
4271 call this%forward(get_sample(input, 1, batch_size, batch_size))
4272
4273 do l = 1, size(this%leaf_vertices)
4274 do s = 1, batch_size
4275 output(l,s)%num_vertices = input(1,s)%num_vertices
4276 output(l,s)%num_edges = input(1,s)%num_edges
4277 output(l,s)%num_vertex_features = this%model( &
4278 this%leaf_vertices(l) &
4279 )%layer%output_shape(1)
4280 output(l,s)%num_edge_features = this%model( &
4281 this%leaf_vertices(l) &
4282 )%layer%output_shape(2)
4283 output(l,s)%vertex_features = this%model( &
4284 this%leaf_vertices(l) &
4285 )%layer%output(1,s)%val
4286 if(size(this%model(this%leaf_vertices(l))%layer%output,1).eq.1)then
4287 output(l,s)%edge_features = input(1,s)%edge_features
4288 else
4289 output(l,s)%edge_features = this%model( &
4290 this%leaf_vertices(l) &
4291 )%layer%output(2,s)%val
4292 end if
4293 end do
4294 end do
4295
4296
4297 !---------------------------------------------------------------------------
4298 ! Restore training/inference mode
4299 !---------------------------------------------------------------------------
4300 call this%restore_mode(mode_store)
4301
4302 end function predict_graph2d
4303 !###############################################################################
4304
4305
4306 !###############################################################################
4307 module function predict_array_from_real( this, input, output_as_array, verbose ) &
4308 result(output)
4309 !! Predict the output for a generic input
4310 implicit none
4311
4312 ! Arguments
4313 class(network_type), intent(inout) :: this
4314 !! Instance of network
4315 class(*), dimension(..), intent(in) :: input
4316 !! Input graph
4317 logical, intent(in) :: output_as_array
4318 !! Whether to output as array
4319 integer, intent(in), optional :: verbose
4320 !! Verbosity level
4321
4322 type(array_type), dimension(:,:), allocatable :: output
4323 !! Predicted output
4324
4325 ! Local variables
4326 integer :: s, i
4327 !! Loop index
4328 integer :: num_samples
4329 !! Number of samples
4330 integer :: verbose_
4331 !! Verbosity level
4332 logical, allocatable :: mode_store(:)
4333 !! Storage for inference mode booleans
4334
4335
4336 !---------------------------------------------------------------------------
4337 ! Initialise optional arguments
4338 !---------------------------------------------------------------------------
4339 if(present(verbose))then
4340 verbose_ = verbose
4341 else
4342 verbose_ = 0
4343 end if
4344 if(.not.output_as_array)then
4345 call stop_program("predict_array_from_real: output_as_array must be true")
4346 return
4347 end if
4348
4349
4350 !---------------------------------------------------------------------------
4351 ! Set number of samples for predicting
4352 !---------------------------------------------------------------------------
4353 num_samples = this%save_input( input )
4354 ! call this%set_batch_size(num_samples)
4355
4356
4357 !---------------------------------------------------------------------------
4358 ! Enable inference mode
4359 !---------------------------------------------------------------------------
4360 call this%set_inference_mode(mode_store)
4361
4362 !---------------------------------------------------------------------------
4363 ! Forward pass
4364 !---------------------------------------------------------------------------
4365 select case(this%use_graph_input)
4366 case(.true.)
4367 call this%forward(this%input_graph)
4368 case default
4369 call this%forward(this%input_array)
4370 end select
4371
4372
4373 !---------------------------------------------------------------------------
4374 ! Allocate output data
4375 !---------------------------------------------------------------------------
4376 allocate(output( &
4377 size(this%model(this%leaf_vertices(1))%layer%output, 1), &
4378 size(this%model(this%leaf_vertices(1))%layer%output, 2) &
4379 ))
4380 do s = 1, size(this%model(this%leaf_vertices(1))%layer%output, 2)
4381 do i = 1, size(this%model(this%leaf_vertices(1))%layer%output, 1)
4382 output(i,s) = this%model(this%leaf_vertices(1))%layer%output(i,s)
4383 end do
4384 end do
4385
4386
4387 !---------------------------------------------------------------------------
4388 ! Restore training/inference mode
4389 !---------------------------------------------------------------------------
4390 call this%restore_mode(mode_store)
4391
4392 end function predict_array_from_real
4393 !###############################################################################
4394
4395
4396 !###############################################################################
4397 module function predict_array( this, input, verbose ) &
4398 result(output)
4399 !! Predict the output for a generic input
4400 implicit none
4401
4402 ! Arguments
4403 class(network_type), intent(inout) :: this
4404 !! Instance of network
4405 class(array_type), dimension(..), intent(in) :: input
4406 !! Input graph
4407 integer, intent(in), optional :: verbose
4408 !! Verbosity level
4409
4410 type(array_type), dimension(:,:), allocatable :: output
4411 !! Predicted output
4412
4413 ! Local variables
4414 integer :: l, s, i, j, layer_id
4415 !! Loop index
4416 integer :: num_samples
4417 !! Number of samples
4418 integer :: verbose_
4419 !! Verbosity level
4420 integer, dimension(2) :: output_shape
4421 !! Output shape
4422 logical, allocatable :: mode_store(:)
4423 !! Storage for inference mode booleans
4424
4425
4426 !---------------------------------------------------------------------------
4427 ! Initialise optional arguments
4428 !---------------------------------------------------------------------------
4429 if(present(verbose))then
4430 verbose_ = verbose
4431 else
4432 verbose_ = 0
4433 end if
4434
4435
4436 !---------------------------------------------------------------------------
4437 ! Set number of samples for predicting
4438 !---------------------------------------------------------------------------
4439 num_samples = this%save_input( input )
4440 ! call this%set_batch_size(num_samples)
4441
4442
4443 !---------------------------------------------------------------------------
4444 ! Enable inference mode
4445 !---------------------------------------------------------------------------
4446 call this%set_inference_mode(mode_store)
4447
4448 !---------------------------------------------------------------------------
4449 ! Forward pass
4450 !---------------------------------------------------------------------------
4451 select case(this%use_graph_input)
4452 case(.true.)
4453 call this%forward(this%input_graph)
4454 case default
4455 call this%forward(this%input_array)
4456 end select
4457
4458
4459 !---------------------------------------------------------------------------
4460 ! Allocate output data
4461 !---------------------------------------------------------------------------
4462 output_shape = this%get_output_shape()
4463 allocate(output(output_shape(1), output_shape(2)))
4464 do l = 1, size(this%leaf_vertices)
4465 layer_id = this%auto_graph%vertex(this%leaf_vertices(l))%id
4466 j = 0
4467 do i = 1, size(this%model(layer_id)%layer%output, 1)
4468 j = j + 1
4469 do s = 1, size(this%model(layer_id)%layer%output, 2)
4470 output(j,s) = this%model(layer_id)%layer%output(i,s)
4471 end do
4472 end do
4473 end do
4474
4475
4476 !---------------------------------------------------------------------------
4477 ! Restore training/inference mode
4478 !---------------------------------------------------------------------------
4479 call this%restore_mode(mode_store)
4480
4481 end function predict_array
4482 !###############################################################################
4483
4484
4485 !###############################################################################
4486 module function predict_generic( this, input, verbose, output_as_graph ) &
4487 result(output)
4488 !! Predict the output for a generic input
4489 implicit none
4490
4491 ! Arguments
4492 class(network_type), intent(inout) :: this
4493 !! Instance of network
4494 class(*), dimension(:,:), intent(in) :: input
4495 !! Input graph
4496 integer, intent(in), optional :: verbose
4497 !! Verbosity level
4498 logical, intent(in), optional :: output_as_graph
4499 !! Boolean whether to output as graph
4500
4501 class(*), dimension(:,:), allocatable :: output
4502 !! Predicted output
4503
4504 ! Local variables
4505 integer :: l, s, i, j, layer_id
4506 !! Loop index
4507 integer :: num_samples
4508 !! Number of samples
4509 integer :: verbose_
4510 !! Verbosity level
4511 logical :: output_as_graph_
4512 !! Output as graph boolean
4513 integer, dimension(2) :: output_shape
4514 !! Output shape
4515 logical, allocatable :: mode_store(:)
4516 !! Storage for inference mode booleans
4517
4518
4519 !---------------------------------------------------------------------------
4520 ! Initialise optional arguments
4521 !---------------------------------------------------------------------------
4522 if(present(verbose))then
4523 verbose_ = verbose
4524 else
4525 verbose_ = 0
4526 end if
4527
4528 if(present(output_as_graph))then
4529 output_as_graph_ = output_as_graph
4530 else
4531 output_as_graph_ = .false.
4532 end if
4533 if(output_as_graph_.and..not.this%use_graph_output)then
4534 call stop_program("output_as_graph is true but network does not use &
4535 &graph output")
4536 end if
4537
4538
4539 !---------------------------------------------------------------------------
4540 ! Set number of samples for predicting
4541 !---------------------------------------------------------------------------
4542 num_samples = this%save_input( input )
4543 call this%set_batch_size(num_samples)
4544
4545
4546 !---------------------------------------------------------------------------
4547 ! Enable inference mode
4548 !---------------------------------------------------------------------------
4549 call this%set_inference_mode(mode_store)
4550
4551 !---------------------------------------------------------------------------
4552 ! Forward pass
4553 !---------------------------------------------------------------------------
4554 select case(this%use_graph_input)
4555 case(.true.)
4556 call this%forward(this%input_graph)
4557 case default
4558 call this%forward(this%input_array)
4559 end select
4560
4561
4562 !---------------------------------------------------------------------------
4563 ! Allocate output data
4564 !---------------------------------------------------------------------------
4565 output_shape = this%get_output_shape()
4566 if(output_as_graph_)then
4567 allocate(output(output_shape(1), output_shape(2)), source = graph_type())
4568 select type(output)
4569 type is(graph_type)
4570 select type(input)
4571 type is(graph_type)
4572 do l = 1, size(this%leaf_vertices)
4573 do s = 1, num_samples
4574 output(l,s)%num_vertices = input(1,s)%num_vertices
4575 output(l,s)%num_edges = input(1,s)%num_edges
4576 output(l,s)%num_vertex_features = this%model( &
4577 this%leaf_vertices(l) &
4578 )%layer%output_shape(1)
4579 output(l,s)%num_edge_features = this%model( &
4580 this%leaf_vertices(l) &
4581 )%layer%output_shape(2)
4582 output(l,s)%vertex_features = this%model( &
4583 this%leaf_vertices(l) &
4584 )%layer%output(1,s)%val
4585 if(size(this%model(this%leaf_vertices(l))%layer%output,1).eq.1)then
4586 output(l,s)%edge_features = input(1,s)%edge_features
4587 else
4588 output(l,s)%edge_features = this%model( &
4589 this%leaf_vertices(l) &
4590 )%layer%output(2,s)%val
4591 end if
4592 end do
4593 end do
4594 class default
4595 call stop_program("input is not of type graph_type")
4596 end select
4597 class default
4598 call stop_program("allocation of output as graph_type failed")
4599 end select
4600 else
4601 output_shape = this%get_output_shape()
4602 allocate(output(output_shape(1), output_shape(2)), source = array_type())
4603 select type(output)
4604 type is(array_type)
4605 do l = 1, size(this%leaf_vertices)
4606 layer_id = this%auto_graph%vertex(this%leaf_vertices(l))%id
4607 j = 0
4608 do i = 1, size(this%model(layer_id)%layer%output, 1)
4609 j = j + 1
4610 do s = 1, size(this%model(layer_id)%layer%output, 2)
4611 output(j,s) = this%model(layer_id)%layer%output(i,s)
4612 end do
4613 end do
4614 end do
4615 end select
4616 end if
4617
4618
4619 !---------------------------------------------------------------------------
4620 ! Restore training/inference mode
4621 !---------------------------------------------------------------------------
4622 call this%restore_mode(mode_store)
4623
4624 end function predict_generic
4625 !###############################################################################
4626
4627
4628 !###############################################################################
4629 module subroutine print_summary(this)
4630 !! Print a summary of the network architecture
4631 implicit none
4632
4633 ! Arguments
4634 class(network_type), intent(in) :: this
4635 !! Instance of network
4636
4637 ! Local variables
4638 integer :: i, vertex_idx
4639 !! Loop index and vertex index
4640 integer :: total_params
4641 !! Parameter counts
4642 integer :: layer_params
4643 !! Parameters in current layer
4644 character(len=80) :: line
4645 !! Line separator
4646 character(len=40) :: layer_name
4647 !! Layer name
4648 character(len=30) :: output_shape_str
4649 !! Output shape string
4650 character(len=20) :: param_str
4651 !! Parameter count string
4652 character(len=100) :: fmt
4653 !! Format string
4654
4655 line = repeat('_', 80)
4656
4657 ! Print header
4658 write(*,*)
4659 write(*,'(A)') line
4660 write(*,'(A)') 'Model Summary'
4661 write(*,'(A)') line
4662 write(*,'(A35, A25, A15)') 'Layer (type)', 'Output Shape', 'Param #'
4663 write(*,'(A)') repeat('=', 80)
4664
4665 ! Initialise parameter count
4666 total_params = 0
4667
4668 ! Print each layer
4669 do i = 1, this%num_layers
4670 vertex_idx = this%vertex_order(i)
4671 associate(layer => this%model(vertex_idx)%layer)
4672 ! Get layer name
4673 if(allocated(layer%name))then
4674 write(layer_name, '(A," (",A,")")') &
4675 trim(layer%name), trim(layer%subtype)
4676 else
4677 write(layer_name, '(A,I0," (",A,")")') &
4678 'layer_', i, trim(layer%subtype)
4679 end if
4680
4681 ! Get output shape string
4682 if(allocated(layer%output_shape))then
4683 ! write the general format for output shape
4684 write(fmt,'("(""(""",A,"I0,"")"")")') &
4685 repeat('I0,", "', size(layer%output_shape)-1)
4686 write(output_shape_str, fmt) layer%output_shape
4687 else
4688 output_shape_str = '(Not set)'
4689 end if
4690
4691 ! Get parameter count
4692 layer_params = layer%get_num_params()
4693 total_params = total_params + layer_params
4694 if(layer_params .gt. 0)then
4695 write(param_str, '(I0)') layer_params
4696 else
4697 param_str = '0'
4698 end if
4699
4700 ! Print layer information
4701 write(*,'(A35, A25, A15)') adjustl(trim(layer_name)), &
4702 adjustl(trim(output_shape_str)), adjustl(trim(param_str))
4703 end associate
4704 end do
4705
4706 ! Print footer
4707 write(*,'(A)') repeat('=', 80)
4708 write(*,'(A,I0)') 'Number of input vertices: ', size(this%root_vertices)
4709 write(*,'(A,I0)') 'Number of output vertices: ', size(this%leaf_vertices)
4710 write(*,'(A,I0)') 'Total trainable params: ', total_params
4711 write(*,'(A)') line
4712 write(*,*)
4713
4714 end subroutine print_summary
4715 !###############################################################################
4716
4717
4718 !###############################################################################
4719 module function inverse_design_real( &
4720 this, target, x_init, optimiser, steps &
4721 ) result(x_opt)
4722 !! Optimise input to match a target output (real inputs).
4723 !! Wraps the array_type implementation after converting real arrays.
4724 implicit none
4725
4726 ! Arguments
4727 class(network_type), intent(inout), target :: this
4728 !! Instance of the network
4729 real(real32), dimension(:,:), intent(in) :: target
4730 !! Target output values
4731 real(real32), dimension(:,:), intent(in) :: x_init
4732 !! Initial input values
4733 class(base_optimiser_type), optional, intent(in) :: optimiser
4734 !! Optimiser for input updates (defaults to network optimiser)
4735 integer, intent(in) :: steps
4736 !! Number of optimisation iterations
4737 real(real32), dimension(size(x_init,1), size(x_init,2)) :: x_opt
4738 !! Optimised input
4739
4740 ! Local variables
4741 type(array_type), pointer :: target_arr(:,:), x_init_arr(:,:), x_opt_arr(:,:)
4742 !! Working input and target as array_type
4743
4744
4745 !---------------------------------------------------------------------------
4746 ! Convert real arrays to array_type
4747 !---------------------------------------------------------------------------
4748 allocate(target_arr(1,1), x_init_arr(1,1), x_opt_arr(1,1))
4749 call target_arr(1,1)%allocate(source=target)
4750 call x_init_arr(1,1)%allocate(source=x_init)
4751
4752 !---------------------------------------------------------------------------
4753 ! Delegate to array_type implementation
4754 !---------------------------------------------------------------------------
4755 x_opt_arr = this%inverse_design_array_2d( &
4756 target_arr, x_init_arr, optimiser, steps &
4757 )
4758 x_opt = x_opt_arr(1,1)%val
4759
4760 call target_arr(1,1)%deallocate()
4761 call x_init_arr(1,1)%deallocate()
4762 call x_opt_arr(1,1)%deallocate()
4763 deallocate(target_arr, x_init_arr, x_opt_arr)
4764
4765 end function inverse_design_real
4766 !###############################################################################
4767
4768
4769 !###############################################################################
4770 module function inverse_design_array_0d( &
4771 this, target, x_init, optimiser, steps &
4772 ) result(x_opt)
4773 !! Optimise the input so the network output matches a target.
4774 !! Wraps the array_type implementation after converting to 2D array.
4775 implicit none
4776
4777 ! Arguments
4778 class(network_type), intent(inout), target :: this
4779 !! Instance of the network
4780 type(array_type), intent(in) :: target
4781 !! Target output values
4782 type(array_type), intent(in) :: x_init
4783 !! Initial input values
4784 class(base_optimiser_type), optional, intent(in) :: optimiser
4785 !! Optimiser for input updates (defaults to network optimiser)
4786 integer, intent(in) :: steps
4787 !! Number of optimisation iterations
4788 type(array_type) :: x_opt
4789 !! Optimised input
4790
4791 ! Local variables
4792 type(array_type), pointer :: target_arr(:,:), x_init_arr(:,:), x_opt_arr(:,:)
4793
4794
4795 !---------------------------------------------------------------------------
4796 ! Convert real arrays to array_type
4797 !---------------------------------------------------------------------------
4798 allocate(target_arr(1,1), x_init_arr(1,1), x_opt_arr(1,1))
4799 call target_arr(1,1)%allocate(source=target)
4800 call x_init_arr(1,1)%allocate(source=x_init)
4801
4802 !---------------------------------------------------------------------------
4803 ! Delegate to array_type implementation
4804 !---------------------------------------------------------------------------
4805 x_opt_arr = this%inverse_design_array_2d( &
4806 target_arr, x_init_arr, optimiser, steps &
4807 )
4808 x_opt = x_opt_arr(1,1)
4809
4810 call target_arr(1,1)%deallocate()
4811 call x_init_arr(1,1)%deallocate()
4812 call x_opt_arr(1,1)%deallocate()
4813 deallocate(target_arr, x_init_arr, x_opt_arr)
4814
4815 end function inverse_design_array_0d
4816 !###############################################################################
4817
4818
4819 !###############################################################################
4820 module function inverse_design_array_2d( &
4821 this, target, x_init, optimiser, steps &
4822 ) result(x_opt)
4823 !! Optimise the input so the network output matches a target.
4824 !! Wraps the array_type implementation after converting to 2D array.
4825 implicit none
4826
4827 ! Arguments
4828 class(network_type), intent(inout), target :: this
4829 !! Instance of the network
4830 type(array_type), dimension(:,:), intent(in) :: target
4831 !! Target output values
4832 type(array_type), dimension(:,:), intent(in) :: x_init
4833 !! Initial input values
4834 class(base_optimiser_type), optional, intent(in) :: optimiser
4835 !! Optimiser for input updates (defaults to network optimiser)
4836 integer, intent(in) :: steps
4837 !! Number of optimisation iterations
4838 type(array_type), dimension(size(x_init,1), size(x_init,2)) :: x_opt
4839 !! Optimised input
4840
4841 ! Local variables
4842 integer :: step, i, j, itmp1, root_id, num_x, num_samples, num_elements
4843 !! Loop index, root layer id, number of input elements
4844 logical :: use_edge_features
4845 !! Whether edge features are used in the input
4846 type(array_type), pointer :: loss
4847 !! Loss pointer
4848 class(base_optimiser_type), allocatable :: opt
4849 !! Local optimiser instance
4850 real(real32), allocatable :: x_flat(:), x_grad(:)
4851 !! Flat input vector and gradient
4852 logical, allocatable :: mode_store(:)
4853 !! Storage for inference mode booleans
4854 real(real32), allocatable :: saved_params(:)
4855 !! Saved network parameters
4856
4857
4858 !---------------------------------------------------------------------------
4859 ! Ensure the network has a loss function
4860 !---------------------------------------------------------------------------
4861 if(.not.allocated(this%loss))then
4862 call this%set_loss("mse")
4863 end if
4864
4865
4866 !---------------------------------------------------------------------------
4867 ! Get number of input elements
4868 !---------------------------------------------------------------------------
4869 num_x = 0
4870 use_edge_features = .false.
4871 if(this%use_graph_input)then
4872 num_samples = size(x_init, dim=2)
4873 num_x = size(x_init(1,1)%val) ! vertex features
4874 ! determine if edge features are used by checking the output shape of the input layer
4875 if(size(this%model(this%root_vertices(1))%layer%output_shape,dim=1).eq.2)then
4876 use_edge_features = .true.
4877 num_x = num_x + size(x_init(2,1)%val) ! edge features
4878 end if
4879 else
4880 num_samples = size(x_init(1,1)%val, dim=2)
4881 do i = 1, size(x_init,1)
4882 do j = 1, size(x_init,2)
4883 num_x = num_x + size(x_init(i,j)%val,dim=1)
4884 end do
4885 end do
4886 end if
4887 x_opt = x_init
4888 if(num_samples.gt.1)then
4889 call stop_program( &
4890 "inverse_design_array_2d: batch size greater than 1 not supported" &
4891 )
4892 end if
4893
4894
4895 !---------------------------------------------------------------------------
4896 ! Set up optimiser for input variables
4897 !---------------------------------------------------------------------------
4898 if(present(optimiser))then
4899 allocate(opt, source=optimiser)
4900 else
4901 allocate(opt, source=base_optimiser_type( &
4902 learning_rate=this%optimiser%learning_rate))
4903 end if
4904 call opt%init_gradients(num_x)
4905 opt%iter = 0
4906
4907
4908 !---------------------------------------------------------------------------
4909 ! Pre-allocate flat arrays used in the optimisation loop
4910 !---------------------------------------------------------------------------
4911 allocate(x_flat(num_x))
4912 allocate(x_grad(num_x))
4913
4914
4915 !---------------------------------------------------------------------------
4916 ! Ensure training mode is active so the full graph is built
4917 !---------------------------------------------------------------------------
4918 call this%set_training_mode(mode_store)
4919
4920
4921 !---------------------------------------------------------------------------
4922 ! Get root layer id
4923 !---------------------------------------------------------------------------
4924 root_id = this%auto_graph%vertex(this%root_vertices(1))%id
4925 call this%set_batch_size(num_samples)
4926
4927
4928 !---------------------------------------------------------------------------
4929 ! Save network parameters so they can be restored afterwards
4930 !---------------------------------------------------------------------------
4931 allocate(saved_params(this%num_params))
4932 saved_params = this%get_params()
4933
4934
4935 !---------------------------------------------------------------------------
4936 ! Optimisation loop
4937 !---------------------------------------------------------------------------
4938 do step = 1, steps
4939
4940 ! Forward pass with current x
4941 call this%forward(x_opt)
4942
4943 ! Enable gradient tracking on the input layer output
4944 if(this%use_graph_input)then
4945 call this%model(root_id)%layer%output(1,1)%set_requires_grad(.true.)
4946 if(use_edge_features)then
4947 call this%model(root_id)%layer%output(2,1)%set_requires_grad(.true.)
4948 end if
4949 else
4950 do i = 1, size(x_opt,1)
4951 do j = 1, size(x_opt,2)
4952 call this%model(root_id)%layer%output(i,j)%set_requires_grad(.true.)
4953 end do
4954 end do
4955 end if
4956
4957 ! Compute loss via the network's loss function
4958 call this%save_output(target)
4959 loss => this%loss_eval(1, num_samples)
4960
4961 ! Backward pass
4962 call loss%grad_reverse()
4963
4964 ! Extract gradient w.r.t. input
4965 itmp1 = 0
4966 if(associated(this%model(root_id)%layer%output(1,1)%grad))then
4967 if(this%use_graph_input)then
4968 num_elements = size(x_opt(1,1)%val, dim=1)
4969 do i = 1, size(x_opt(1,1)%val, dim=2)
4970 itmp1 = itmp1 + 1
4971 x_grad(itmp1:itmp1+num_elements-1) = &
4972 this%model(root_id)%layer%output(1,1)%grad%val(:,i)
4973 x_flat(itmp1:itmp1+num_elements-1) = &
4974 x_opt(1,1)%val(:,i)
4975 itmp1 = itmp1 + num_elements - 1
4976 end do
4977 if(use_edge_features)then
4978 num_elements = size(x_opt(1,1)%val, dim=1)
4979 do i = 1, size(x_opt(2,1)%val, dim=2)
4980 itmp1 = itmp1 + 1
4981 x_grad(itmp1:itmp1+num_elements-1) = &
4982 this%model(root_id)%layer%output(2,1)%grad%val(:,i)
4983 x_flat(itmp1:itmp1+num_elements-1) = &
4984 x_opt(2,1)%val(:,i)
4985 itmp1 = itmp1 + num_elements - 1
4986 end do
4987 end if
4988 else
4989 do i = 1, size(x_opt,1)
4990 do j = 1, size(x_opt,2)
4991 num_elements = size(x_opt(i,j)%val, dim=1)
4992 itmp1 = itmp1 + 1
4993 x_grad(itmp1:itmp1+num_elements-1) = &
4994 this%model(root_id)%layer%output(i,j)%grad%val(:,1)
4995 x_flat(itmp1:itmp1+num_elements-1) = &
4996 x_opt(i,j)%val(:,1)
4997 itmp1 = itmp1 + num_elements - 1
4998 end do
4999 end do
5000 end if
5001 else
5002 x_grad = 0._real32
5003 end if
5004
5005 ! Update x using the optimiser (not the model weights)
5006 opt%iter = opt%iter + 1
5007 call opt%minimise(x_flat, x_grad)
5008
5009 ! Convert flat x back to array form
5010 itmp1 = 0
5011 if(this%use_graph_input)then
5012 do i = 1, size(x_opt(1,1)%val, dim=2)
5013 itmp1 = itmp1 + 1
5014 x_opt(1,1)%val(:,i) = x_flat(itmp1:itmp1+size(x_opt(1,1)%val, dim=1)-1)
5015 itmp1 = itmp1 + size(x_opt(1,1)%val, dim=1) - 1
5016 end do
5017 if(use_edge_features)then
5018 do i = 1, size(x_opt(2,1)%val, dim=2)
5019 itmp1 = itmp1 + 1
5020 x_opt(2,1)%val(:,i) = x_flat(itmp1:itmp1+size(x_opt(2,1)%val, dim=1)-1)
5021 itmp1 = itmp1 + size(x_opt(2,1)%val, dim=1) - 1
5022 end do
5023 end if
5024 else
5025 do i = 1, size(x_opt,1)
5026 do j = 1, size(x_opt,2)
5027 itmp1 = itmp1 + 1
5028 x_opt(i,j)%val(:,1) = x_flat(itmp1:itmp1+size(x_opt(i,j)%val, dim=1)-1)
5029 itmp1 = itmp1 + size(x_opt(i,j)%val, dim=1) - 1
5030 end do
5031 end do
5032 end if
5033
5034 ! Clean up computation graph
5035 call loss%nullify_graph()
5036 deallocate(loss)
5037 nullify(loss)
5038
5039 ! Reset network parameter gradients so they remain unchanged
5040 call this%reset_gradients()
5041
5042 end do
5043
5044
5045 !---------------------------------------------------------------------------
5046 ! Restore training/inference mode
5047 !---------------------------------------------------------------------------
5048 call this%restore_mode(mode_store)
5049
5050
5051 !---------------------------------------------------------------------------
5052 ! Restore network parameters to ensure model is unchanged
5053 !---------------------------------------------------------------------------
5054 call this%set_params(saved_params)
5055
5056 end function inverse_design_array_2d
5057 !###############################################################################
5058
5059
169/310
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✓ Branch 17 taken 3 times.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 51 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 51 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 51 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 50 times.
✓ Branch 27 taken 1 times.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 60 times.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 54 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 54 times.
✓ Branch 42 taken 4 times.
✓ Branch 43 taken 50 times.
✓ Branch 45 taken 50 times.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 48 taken 28 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 28 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 28 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 86 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 86 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 86 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 140 times.
✗ Branch 68 not taken.
✓ Branch 69 taken 140 times.
✓ Branch 72 taken 54 times.
✓ Branch 73 taken 86 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 86 times.
✗ Branch 77 not taken.
✓ Branch 78 taken 140 times.
✗ Branch 80 not taken.
✓ Branch 81 taken 140 times.
✓ Branch 84 taken 77 times.
✓ Branch 85 taken 63 times.
✗ Branch 86 not taken.
✓ Branch 87 taken 140 times.
✗ Branch 89 not taken.
✓ Branch 90 taken 140 times.
✓ Branch 93 taken 77 times.
✓ Branch 94 taken 63 times.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✓ Branch 104 taken 13 times.
✗ Branch 105 not taken.
✓ Branch 106 taken 13 times.
✗ Branch 107 not taken.
✓ Branch 108 taken 13 times.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✓ Branch 119 taken 153 times.
✗ Branch 121 not taken.
✓ Branch 122 taken 153 times.
✓ Branch 125 taken 85 times.
✓ Branch 126 taken 68 times.
✗ Branch 127 not taken.
✓ Branch 128 taken 7 times.
✗ Branch 130 not taken.
✓ Branch 131 taken 7 times.
✓ Branch 134 taken 4 times.
✓ Branch 135 taken 3 times.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 164 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 168 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 171 not taken.
✓ Branch 172 taken 3330 times.
✗ Branch 174 not taken.
✓ Branch 175 taken 3330 times.
✓ Branch 178 taken 2216 times.
✓ Branch 179 taken 1114 times.
✓ Branch 180 taken 6 times.
✓ Branch 181 taken 1710 times.
✓ Branch 182 taken 2 times.
✓ Branch 183 taken 1708 times.
✗ Branch 184 not taken.
✓ Branch 185 taken 1708 times.
✓ Branch 187 taken 1708 times.
✗ Branch 188 not taken.
✓ Branch 189 taken 18 times.
✓ Branch 190 taken 1727 times.
✗ Branch 191 not taken.
✓ Branch 192 taken 1745 times.
✗ Branch 194 not taken.
✓ Branch 195 taken 1745 times.
✓ Branch 198 taken 1745 times.
✗ Branch 199 not taken.
✓ Branch 200 taken 18 times.
✓ Branch 201 taken 1727 times.
✓ Branch 202 taken 15 times.
✓ Branch 203 taken 1712 times.
✓ Branch 205 taken 1712 times.
✗ Branch 206 not taken.
✓ Branch 207 taken 24 times.
✓ Branch 208 taken 3448 times.
✗ Branch 209 not taken.
✗ Branch 210 not taken.
✗ Branch 212 not taken.
✗ Branch 213 not taken.
✗ Branch 216 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 219 not taken.
✗ Branch 221 not taken.
✗ Branch 222 not taken.
✗ Branch 225 not taken.
✗ Branch 226 not taken.
✗ Branch 227 not taken.
✓ Branch 228 taken 4427 times.
✗ Branch 230 not taken.
✓ Branch 231 taken 4427 times.
✓ Branch 234 taken 4427 times.
✗ Branch 235 not taken.
✗ Branch 236 not taken.
✗ Branch 237 not taken.
✗ Branch 239 not taken.
✗ Branch 240 not taken.
✗ Branch 243 not taken.
✗ Branch 244 not taken.
✗ Branch 245 not taken.
✓ Branch 246 taken 4427 times.
✗ Branch 248 not taken.
✓ Branch 249 taken 4427 times.
✓ Branch 252 taken 4427 times.
✗ Branch 253 not taken.
✓ Branch 254 taken 1227 times.
✓ Branch 255 taken 3 times.
✓ Branch 256 taken 1227 times.
✗ Branch 257 not taken.
✓ Branch 258 taken 3 times.
✓ Branch 259 taken 1227 times.
✓ Branch 261 taken 1 times.
✓ Branch 262 taken 2 times.
✓ Branch 264 taken 1 times.
✓ Branch 265 taken 1 times.
✓ Branch 266 taken 8 times.
✓ Branch 267 taken 1219 times.
✓ Branch 268 taken 1 times.
✓ Branch 269 taken 7 times.
✓ Branch 271 taken 3 times.
✓ Branch 272 taken 4 times.
✓ Branch 274 taken 2 times.
✓ Branch 275 taken 2 times.
✓ Branch 277 taken 1 times.
✓ Branch 278 taken 1 times.
✓ Branch 279 taken 1212 times.
✓ Branch 280 taken 7 times.
✓ Branch 281 taken 2 times.
✓ Branch 282 taken 1210 times.
✓ Branch 284 taken 1204 times.
✓ Branch 285 taken 6 times.
✓ Branch 287 taken 5 times.
✓ Branch 288 taken 1 times.
✓ Branch 289 taken 2 times.
✓ Branch 290 taken 5 times.
✓ Branch 291 taken 1 times.
✓ Branch 292 taken 1 times.
✓ Branch 293 taken 2 times.
✓ Branch 294 taken 3 times.
✓ Branch 295 taken 1 times.
✓ Branch 296 taken 1 times.
✓ Branch 297 taken 2 times.
✓ Branch 298 taken 1 times.
✓ Branch 299 taken 1 times.
✓ Branch 300 taken 1 times.
✓ Branch 301 taken 1221 times.
✓ Branch 302 taken 2 times.
✓ Branch 303 taken 1221 times.
✗ Branch 304 not taken.
✓ Branch 305 taken 2 times.
✓ Branch 306 taken 1221 times.
✓ Branch 307 taken 7 times.
✓ Branch 308 taken 1214 times.
✓ Branch 309 taken 1211 times.
✓ Branch 310 taken 3 times.
✓ Branch 312 taken 1204 times.
✓ Branch 313 taken 7 times.
✓ Branch 314 taken 17 times.
✓ Branch 315 taken 2 times.
✓ Branch 316 taken 17 times.
✗ Branch 317 not taken.
✓ Branch 318 taken 2 times.
✓ Branch 319 taken 17 times.
✗ Branch 320 not taken.
✓ Branch 321 taken 2 times.
✓ Branch 322 taken 1 times.
✓ Branch 323 taken 1 times.
✓ Branch 325 taken 1 times.
✗ Branch 326 not taken.
✓ Branch 327 taken 7 times.
✓ Branch 328 taken 10 times.
✓ Branch 329 taken 1 times.
✓ Branch 330 taken 6 times.
✓ Branch 331 taken 1 times.
✓ Branch 332 taken 5 times.
✓ Branch 333 taken 2 times.
✓ Branch 334 taken 3 times.
✓ Branch 336 taken 3 times.
✗ Branch 337 not taken.
✓ Branch 338 taken 7 times.
✓ Branch 339 taken 3 times.
✓ Branch 340 taken 2 times.
✓ Branch 341 taken 5 times.
✓ Branch 342 taken 5 times.
✗ Branch 343 not taken.
✗ Branch 344 not taken.
✗ Branch 345 not taken.
✓ Branch 346 taken 1 times.
✓ Branch 347 taken 2 times.
✓ Branch 348 taken 1 times.
✗ Branch 349 not taken.
✓ Branch 350 taken 1 times.
✓ Branch 351 taken 1 times.
✓ Branch 352 taken 1 times.
✗ Branch 353 not taken.
✓ Branch 354 taken 1 times.
✗ Branch 355 not taken.
✓ Branch 356 taken 1 times.
✗ Branch 357 not taken.
✓ Branch 358 taken 1 times.
✓ Branch 359 taken 604 times.
✗ Branch 360 not taken.
✓ Branch 361 taken 604 times.
✗ Branch 362 not taken.
✓ Branch 363 taken 604 times.
✓ Branch 365 taken 604 times.
✗ Branch 366 not taken.
✓ Branch 367 taken 13 times.
✗ Branch 368 not taken.
✓ Branch 369 taken 13 times.
✗ Branch 370 not taken.
✓ Branch 371 taken 13 times.
✗ Branch 372 not taken.
✗ Branch 373 not taken.
✗ Branch 374 not taken.
✗ Branch 375 not taken.
✗ Branch 376 not taken.
✗ Branch 377 not taken.
✗ Branch 378 not taken.
✗ Branch 379 not taken.
✗ Branch 380 not taken.
✗ Branch 381 not taken.
✗ Branch 382 not taken.
✗ Branch 383 not taken.
✗ Branch 384 not taken.
✗ Branch 385 not taken.
✗ Branch 386 not taken.
24836 end submodule athena__network_submodule
5060