diff --git a/example/concurrent-inferences.f90 b/example/concurrent-inferences.f90
index 65e35d0f8..8a350e848 100644
--- a/example/concurrent-inferences.f90
+++ b/example/concurrent-inferences.f90
@@ -3,7 +3,7 @@
 program concurrent_inferences
   !! This program demonstrates how to read a neural network from a JSON file
   !! and use the network to perform concurrent inferences.
-  use inference_engine_m, only : inference_engine_t, tensor_t, infer
+  use inference_engine_m, only : inference_engine_t, tensor_t, infer, numerics_t
   use sourcery_m, only : string_t, command_line_t, file_t
   use assert_m, only : assert
   use iso_fortran_env, only : int64, real64
@@ -40,10 +40,12 @@ program concurrent_inferences
 
     block 
       integer(int64) t_start, t_finish, clock_rate
+      type(numerics_t) :: numerics
+      numerics = inference_engine%to_numerics()
 
       print *,"Performing elemental inferences"
       call system_clock(t_start, clock_rate)
-      outputs = inference_engine%infer(inputs)  ! implicit allocation of outputs array
+      outputs = numerics%infer(inputs)  ! implicit allocation of outputs array
       call system_clock(t_finish)
       print *,"Elemental inference time: ", real(t_finish - t_start, real64)/real(clock_rate, real64)
 
@@ -54,7 +56,7 @@ program concurrent_inferences
       do k=1,lev
         do j=1,lon
           do i=1,lat
-            outputs(i,j,k) = inference_engine%infer(inputs(i,j,k))
+            outputs(i,j,k) = numerics%infer(inputs(i,j,k))
           end do
         end do
       end do
@@ -64,7 +66,7 @@ program concurrent_inferences
       print *,"Performing concurrent inference"
       call system_clock(t_start)
       do concurrent(i=1:lat, j=1:lon, k=1:lev)
-        outputs(i,j,k) = inference_engine%infer(inputs(i,j,k))           
+        outputs(i,j,k) = numerics%infer(inputs(i,j,k))
       end do
       call system_clock(t_finish)
       print *,"Concurrent inference time: ", real(t_finish - t_start, real64)/real(clock_rate, real64)
@@ -72,7 +74,7 @@ program concurrent_inferences
       print *,"Performing concurrent inference with a non-type-bound inference procedure"
       call system_clock(t_start)
       do concurrent(i=1:lat, j=1:lon, k=1:lev)
-        outputs(i,j,k) = infer(inference_engine, inputs(i,j,k))           
+        outputs(i,j,k) = infer(numerics, inputs(i,j,k))
       end do
       call system_clock(t_finish)
       print *,"Concurrent inference time with non-type-bound procedure: ", real(t_finish - t_start, real64)/real(clock_rate, real64)
diff --git a/example/write-read-infer.F90 b/example/write-read-infer.F90
index ff9688760..c688e15df 100644
--- a/example/write-read-infer.F90
+++ b/example/write-read-infer.F90
@@ -7,7 +7,7 @@ program write_read_infer
   !! perform inference.  The network performs an identity mapping from any
   !! non-negative inputs to the corresponding outputs using a RELU activation
   !! function.
-  use inference_engine_m, only : inference_engine_t, relu_t, tensor_t
+  use inference_engine_m, only : inference_engine_t, relu_t, tensor_t, numerics_t
   use sourcery_m, only : string_t, command_line_t, file_t
   use kind_parameters_m, only : rkind
   implicit none
@@ -82,7 +82,11 @@ subroutine write_read_query_infer(output_file_name)
     print *, "Performing inference:"
     inputs = tensor_t([2.,3.])
     print *, "Inputs: ", inputs%values()
-    outputs = inference_engine%infer(inputs)
+    block
+      type(numerics_t) :: numerics
+      numerics = inference_engine%to_numerics()
+      outputs = numerics%infer(inputs)
+    end block
     print *, "Actual outputs: ", outputs%values()
     print *, "Correct outputs:  ", inputs%values()
   end subroutine write_read_query_infer
diff --git a/src/inference_engine/inference_engine_m_.f90 b/src/inference_engine/inference_engine_m_.f90
index 9edc2af85..f7c4f9691 100644
--- a/src/inference_engine/inference_engine_m_.f90
+++ b/src/inference_engine/inference_engine_m_.f90
@@ -15,13 +15,13 @@ module inference_engine_m_
   public :: inference_engine_t
   public :: difference_t
   public :: exchange_t
-  public :: infer
+  public :: numerics_t, infer
 
   character(len=*), parameter :: key(*) = [character(len=len("usingSkipConnections")) :: &
     "modelName", "modelAuthor", "compilationDate", "activationFunction", "usingSkipConnections"]
 
   type inference_engine_t
-    !! Encapsulate the minimal information needed to perform inference
+    !! Encapsulate the information needed to perform inference
     private
     type(tensor_range_t) input_range_, output_range_
     type(string_t) metadata_(size(key))
@@ -29,7 +29,7 @@ module inference_engine_m_
     integer, allocatable :: nodes_(:)
     class(activation_strategy_t), allocatable :: activation_strategy_ ! Strategy Pattern facilitates elemental activation
   contains
-    procedure :: infer
+    procedure :: to_numerics
     procedure :: to_json
     procedure :: map_to_input_range
     procedure :: map_from_output_range
@@ -44,6 +44,17 @@ module inference_engine_m_
     procedure :: to_exchange
   end type
 
+  type numerics_t
+    !! Encapsulate the minimal information needed to perform inference
+    private
+    type(tensor_range_t) input_range_, output_range_
+    real(rkind), allocatable :: weights_(:,:,:), biases_(:,:)
+    integer, allocatable :: nodes_(:)
+    class(activation_strategy_t), allocatable :: activation_strategy_ ! Strategy Pattern facilitates elemental activation
+  contains
+    procedure :: infer
+  end type
+
   type exchange_t
     type(tensor_range_t) input_range_, output_range_
     type(string_t) metadata_(size(key))
@@ -104,6 +115,12 @@ pure module function to_exchange(self) result(exchange)
       type(exchange_t) exchange
     end function
 
+    pure elemental module function to_numerics(self) result(numerics)
+      implicit none
+      class(inference_engine_t), intent(in) :: self
+      type(numerics_t) numerics
+    end function
+
     impure elemental module function to_json(self) result(json_file)
       implicit none
       class(inference_engine_t), intent(in) :: self
@@ -131,7 +148,7 @@ elemental module subroutine assert_conformable_with(self, inference_engine)
 
     elemental module function infer(self, inputs) result(outputs)
       implicit none
-      class(inference_engine_t), intent(in) :: self
+      class(numerics_t), intent(in) :: self
       type(tensor_t), intent(in) :: inputs
       type(tensor_t) outputs
     end function
diff --git a/src/inference_engine/inference_engine_s.F90 b/src/inference_engine/inference_engine_s.F90
index ae7172833..84f46a691 100644
--- a/src/inference_engine/inference_engine_s.F90
+++ b/src/inference_engine/inference_engine_s.F90
@@ -42,7 +42,7 @@
     integer, parameter :: input_layer = 0
     integer k, l
 
-    call assert_consistency(self)
+    call numerics_consistency(self%weights_, self%biases_, self%nodes_, self%activation_strategy_)
 
     associate(w => self%weights_, b => self%biases_, n => self%nodes_, output_layer => ubound(self%nodes_,1))
 
@@ -86,24 +86,30 @@
   end procedure
 
   pure subroutine inference_engine_consistency(self)
-
     type(inference_engine_t), intent(in) :: self
+    call numerics_consistency(self%weights_, self%biases_, self%nodes_, self%activation_strategy_)
+  end subroutine
+
+  pure subroutine numerics_consistency(weights, biases, nodes, activation_strategy)
+    real(rkind), allocatable, intent(in) :: weights(:,:,:), biases(:,:)
+    integer, allocatable, intent(in) :: nodes(:)
+    class(activation_strategy_t), allocatable, intent(in) :: activation_strategy
 
     integer, parameter :: input_layer=0
 
     associate( &
-      all_allocated=>[allocated(self%weights_),allocated(self%biases_),allocated(self%nodes_),allocated(self%activation_strategy_)]&
+      all_allocated=>[allocated(weights),allocated(biases),allocated(nodes),allocated(activation_strategy)]&
     )   
       call assert(all(all_allocated),"inference_engine_s(inference_engine_consistency): fully_allocated", &
         intrinsic_array_t(all_allocated))
     end associate
 
-    associate(max_width=>maxval(self%nodes_), component_dims=>[size(self%biases_,1), size(self%weights_,1), size(self%weights_,2)])
+    associate(max_width=>maxval(nodes), component_dims=>[size(biases,1), size(weights,1), size(weights,2)])
       call assert(all(component_dims == max_width), "inference_engine_s(inference_engine_consistency): conformable arrays", &
         intrinsic_array_t([max_width,component_dims]))
     end associate
 
-    associate(input_subscript => lbound(self%nodes_,1))
+    associate(input_subscript => lbound(nodes,1))
       call assert(input_subscript == input_layer, "inference_engine_s(inference_engine_consistency): n base subsscript", &
         input_subscript)
     end associate
@@ -390,6 +396,15 @@ function get_key_value(line) result(value_)
     node_count = self%nodes_
   end procedure
 
+  module procedure to_numerics
+    numerics%input_range_ = self%input_range_
+    numerics%output_range_ = self%output_range_
+    numerics%weights_ = self%weights_
+    numerics%biases_ = self%biases_
+    numerics%nodes_ = self%nodes_
+    numerics%activation_strategy_ = self%activation_strategy_
+  end procedure
+
   module procedure to_json
 
     type(string_t), allocatable :: lines(:)
diff --git a/src/inference_engine_m.f90 b/src/inference_engine_m.f90
index 02a3868ec..436016c56 100644
--- a/src/inference_engine_m.f90
+++ b/src/inference_engine_m.f90
@@ -6,7 +6,7 @@ module inference_engine_m
  use differentiable_activation_strategy_m, only : differentiable_activation_strategy_t
  use hyperparameters_m, only : hyperparameters_t
  use input_output_pair_m, only : input_output_pair_t, shuffle
- use inference_engine_m_, only : inference_engine_t, difference_t, infer
+ use inference_engine_m_, only : inference_engine_t, difference_t, numerics_t, infer
  use kind_parameters_m, only : rkind
  use mini_batch_m, only : mini_batch_t
  use network_configuration_m, only : network_configuration_t
diff --git a/test/asymmetric_engine_test_m.F90 b/test/asymmetric_engine_test_m.F90
index bf6a04f15..06a5b8400 100644
--- a/test/asymmetric_engine_test_m.F90
+++ b/test/asymmetric_engine_test_m.F90
@@ -9,7 +9,7 @@ module asymmetric_engine_test_m
     test_t, test_result_t, vector_test_description_t, test_description_substring, string_t, vector_function_strategy_t
 
   ! Internal dependencies
-  use inference_engine_m, only : inference_engine_t, tensor_t
+  use inference_engine_m, only : inference_engine_t, tensor_t, numerics_t
   use kind_parameters_m, only : rkind
 
   implicit none
@@ -122,11 +122,13 @@ function xor_and_2nd_input_truth_table() result(test_passes)
     block
       real(rkind), parameter :: tolerance = 1.E-08_rkind, false = 0._rkind, true = 1._rkind
       type(tensor_t) true_true, true_false, false_true, false_false
+      type(numerics_t) :: numerics
+      numerics = asymmetric%to_numerics()
 
-      true_true = asymmetric%infer(tensor_t([true,true]))
-      true_false = asymmetric%infer(tensor_t([true,false]))
-      false_true = asymmetric%infer(tensor_t([false,true]))
-      false_false = asymmetric%infer(tensor_t([false,false]))
+      true_true = numerics%infer(tensor_t([true,true]))
+      true_false = numerics%infer(tensor_t([true,false]))
+      false_true = numerics%infer(tensor_t([false,true]))
+      false_false = numerics%infer(tensor_t([false,false]))
 
       associate( &
         true_true_outputs => true_true%values(), &
diff --git a/test/inference_engine_test_m.F90 b/test/inference_engine_test_m.F90
index d351842ee..c7f23ef1a 100644
--- a/test/inference_engine_test_m.F90
+++ b/test/inference_engine_test_m.F90
@@ -12,7 +12,7 @@ module inference_engine_test_m
 #endif
 
   ! Internal dependencies
-  use inference_engine_m, only : inference_engine_t, tensor_t, difference_t
+  use inference_engine_m, only : inference_engine_t, tensor_t, difference_t, numerics_t
 
   implicit none
 
@@ -132,9 +132,11 @@ function elemental_infer_with_1_hidden_layer_xor_net() result(test_passes)
       type(tensor_t), allocatable :: truth_table(:)
       real(rkind), parameter :: tolerance = 1.E-08_rkind, false = 0._rkind, true = 1._rkind
       integer i
+      type(numerics_t) :: numerics
+      numerics = inference_engine%to_numerics()
 
       associate(array_of_inputs => [tensor_t([true,true]), tensor_t([true,false]), tensor_t([false,true]), tensor_t([false,false])])
-        truth_table = inference_engine%infer(array_of_inputs)
+        truth_table = numerics%infer(array_of_inputs)
       end associate
       test_passes = all( &
         abs(truth_table(1)%values() - false) < tolerance .and. abs(truth_table(2)%values() - true) < tolerance .and. &
@@ -153,9 +155,11 @@ function elemental_infer_with_2_hidden_layer_xor_net() result(test_passes)
       type(tensor_t), allocatable :: truth_table(:)
       real(rkind), parameter :: tolerance = 1.E-08_rkind, false = 0._rkind, true = 1._rkind
       integer i
+      type(numerics_t) :: numerics
+      numerics = inference_engine%to_numerics()
 
       associate(array_of_inputs => [tensor_t([true,true]), tensor_t([true,false]), tensor_t([false,true]), tensor_t([false,false])])
-        truth_table = inference_engine%infer(array_of_inputs)
+        truth_table = numerics%infer(array_of_inputs)
       end associate
       test_passes = all( &
         abs(truth_table(1)%values() - false) < tolerance .and. abs(truth_table(2)%values() - true) < tolerance .and. &
