Commit f49fcd3d authored by Martin Beseda's avatar Martin Beseda

TMP (Uncompilable): Started writing neuron_m module, fixed Doxygen comments

parent 632282cb
......@@ -6,3 +6,4 @@
compilers.env
*TestRunner*
*_fun.f90
src/funit.tmp
......@@ -2375,7 +2375,7 @@ DOT_IMAGE_FORMAT = png
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
INTERACTIVE_SVG = NO
INTERACTIVE_SVG = YES
# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
......
......@@ -11,7 +11,7 @@
BUILD_TYPE=Debug
# Turn of/off time profiling (1/0)
WITH_TIME_PROFILING=0
WITH_TIME_PROFILIN=1
#--------------#----------------------------------------------------------
# Library path #
......
echo "Generating documentation into folder 'docs'...";
doxygen >/dev/null && echo "Documenation was generated." || exit -1;
doxygen 2>&1 >/dev/null | grep -v 'normal_m.f90' && echo "Documenation was generated." || exit -1;
cd docs/latex;
echo "Building LaTeX documentation../";
make >/dev/null && echo "Documentation was built." || exit -1;
......
......@@ -4,3 +4,4 @@ rm -rf build
rm -rf docs/*
rm -f src/*TestRunner*
rm -f src/*.o src/*.mod
rm -f src/funit.tmp
......@@ -10,7 +10,13 @@ echo "#------------------#"
FUNIT_SCRIPTS=connection_m
cd src;
for F in ${FUNIT_SCRIPTS}; do
funit ${F};
funit ${F} 2>&1 |tee funit.tmp;
TEST_STATUS=`grep 'failed <<<<<' funit.tmp` | wc -l
if [[ TEST_STATUS -gt 0 ]]; then
echo "ERROR: Unit test failed!"
exit -1;
fi
done
echo "#---------------------#-------------------------------------------------------------------------------"
......
project(Modules)
enable_language(Fortran)
add_library(neuron_dummy_m SHARED neuron_dummy_m.f90)
set_target_properties(neuron_dummy_m PROPERTIES LINKER_LANGUAGE Fortran)
add_library(time_measurement_m SHARED time_measurement_m.f90)
set_target_properties(time_measurement_m PROPERTIES LINKER_LANGUAGE Fortran)
add_library(normal_m SHARED normal_m.f90)
set_target_properties(normal_m PROPERTIES LINKER_LANGUAGE Fortran)
add_library(neuron_m SHARED neuron_m.f90)
set_target_properties(neuron_m PROPERTIES LINKER_LANGUAGE Fortran)
target_link_libraries(neuron_m time_measurement_m)
add_library(connection_m SHARED connection_m.f90)
set_target_properties(connection_m PROPERTIES LINKER_LANGUAGE Fortran)
target_link_libraries(connection_m neuron_dummy_m time_measurement_m normal_m)
target_link_libraries(connection_m neuron_m time_measurement_m normal_m)
!> Module containing classes representing connections (synapses)
!! in neural networks.
!!
!! It uses `neuron_t` class.
!! It uses 'neuron_m' and 'time_measurement_m' modules.
!!
!! @author Martin Beseda
!! @author Martin Mrovec
!! @date 2017
!! @todo Rewrite pass_signal method of interval_connection_t
module connection_m
use neuron_dummy_m
use neuron_m
use time_measurement_m
use normal_m
......@@ -33,10 +33,10 @@ module connection_m
!> Initializes the common connection_t class components
!! 'input_neuron', 'output_neuron' and 'weight'.
!! I.e. serves similarly to an abstract constructor.
!! @param input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param output_neuron Pointer to the output neuron (instance of neuron_t)
!! @param weight Weight of the connection (real number)
procedure, private :: init_components => init_components_impl
!! @param[in] input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param[in] output_neuron Pointer to the output neuron (instance of neuron_t)
!! @param[in] weight Weight of the connection (real number)
procedure, private :: init_components => connection_init_components_impl
!> Nullifies pointers to input and output neurons, so they
!! don't get destroyed when the connection_t instance is
......@@ -45,7 +45,7 @@ module connection_m
!> Adds a given value to the current weight of the
!! connection.
!! @param added_value Number (real) to be added to the current weight
!! @param[in] added_value Number (real) to be added to the current weight
procedure :: adjust_weight => adjust_weight_impl
!> Getter for the private 'input_neuron' component
......@@ -65,21 +65,24 @@ module connection_m
!! to an output neuron.
procedure :: pass_signal => pass_signal_impl
!> Desctructors for instances of the class connection_t
final :: destroy_connection, destroy_connection_array
!> Scalar desctructor for single instances of the class connection_t
final :: destroy_connection
!> Array desctructor for arrays of instances of the class connection_t
final :: destroy_connection_array
end type connection_t
interface connection_t
!> Constructor of connection_t class
!! @param input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param output_neuron Pointer to the output neuron (instance of neuron_t)
!! @param[in] input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param[in] output_neuron Pointer to the output neuron (instance of neuron_t)
module procedure :: new_connection_2
!> Constructor of connection_t class
!! @param input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param output_neuron Pointer to the output neuron (instance of neuron_t)
!! @param weight Weight of the connection (real number)
!! @param[in] input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param[in] output_neuron Pointer to the output neuron (instance of neuron_t)
!! @param[in] weight Weight of the connection (real number)
module procedure :: new_connection_3
end interface connection_t
......@@ -99,14 +102,14 @@ module connection_m
interface interval_connection_t
!> Constructor of interval_connection_t class
!! @param input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param output_neuron Pointer to the output neuron (instance of neuron_t)
!! @param[in] input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param[in] output_neuron Pointer to the output neuron (instance of neuron_t)
module procedure :: new_interval_connection_2
!> Constructor of interval_connection_t class
!! @param input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param output_neuron Pointer to the output neuron (instance of neuron_t)
!! @param weight Weight of the connection (real number)
!! @param[in] input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param[in] output_neuron Pointer to the output neuron (instance of neuron_t)
!! @param[in] weight Weight of the connection (real number)
module procedure :: new_interval_connection_3
end interface interval_connection_t
......@@ -122,15 +125,19 @@ module connection_m
!--------------!----------------------------------------------------------------------------
! Constructors !
!--------------!
!> Constructor of connection_t class
!! @param[in] input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param[in] output_neuron Pointer to the output neuron (instance of neuron_t)
function new_connection_2(input_neuron, output_neuron) result(new_obj)
type(neuron_t), pointer, intent(in) :: input_neuron
type(neuron_t), pointer, intent(in) :: output_neuron
real :: weight
type(connection_t), pointer :: new_obj
integer :: values(8) !< values(8) is used as seed
class(neuron_t), pointer, intent(in) :: input_neuron
class(neuron_t), pointer, intent(in) :: output_neuron
real :: weight
type(connection_t), pointer :: new_obj
integer :: values(8) !< values(8) is used as seed
#ifdef TIME_PROFILING
real :: start_time
real :: start_time
call time_profiling_start(start_time)
#endif
allocate(new_obj)
......@@ -146,14 +153,17 @@ module connection_m
#endif
end function new_connection_2
!> Constructor of connection_t class
!! @param[in] input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param[in] output_neuron Pointer to the output neuron (instance of neuron_t)
!! @param[in] weight Weight of the connection (real number)
function new_connection_3(input_neuron, output_neuron, weight) result(new_obj)
type(neuron_t), pointer, intent(in) :: input_neuron
type(neuron_t), pointer, intent(in) :: output_neuron
real, intent(in) :: weight
type(connection_t), pointer :: new_obj
class(neuron_t), pointer, intent(in) :: input_neuron
class(neuron_t), pointer, intent(in) :: output_neuron
real, intent(in) :: weight
type(connection_t), pointer :: new_obj
#ifdef TIME_PROFILING
real :: start_time
real :: start_time
call time_profiling_start(start_time)
#endif
allocate(new_obj)
......@@ -167,6 +177,8 @@ module connection_m
!-------------!--------------------------------------------------------------------------
! Destructors !
!-------------!
!> Scalar desctructor for single instances of the class connection_t
subroutine destroy_connection(this)
type(connection_t), intent(inout) :: this
#ifdef TIME_PROFILING
......@@ -179,6 +191,7 @@ module connection_m
#endif
end subroutine destroy_connection
!> Array desctructor for arrays of instances of the class connection_t
subroutine destroy_connection_array(this)
type(connection_t), intent(inout) :: this(:)
integer :: i
......@@ -197,6 +210,9 @@ module connection_m
!-------------------!-------------------------------------------------------------------
! Getters & Setters !
!-------------------!
!> Getter for the private 'input_neuron' component
!! @return Pointer to the input neuron (type neuron_t, pointer)
function get_input_neuron_impl(this) result (input_neuron)
class(connection_t), target, intent(in) :: this
class(neuron_t), pointer :: input_neuron
......@@ -210,6 +226,8 @@ module connection_m
#endif
end function get_input_neuron_impl
!> Getter for the private 'output_neuron' component
!! @return Pointer to the output neuron (type neuron_t, pointer)
function get_output_neuron_impl(this) result (output_neuron)
class(connection_t), target, intent(in) :: this
class(neuron_t), pointer :: output_neuron
......@@ -223,6 +241,8 @@ module connection_m
#endif
end function get_output_neuron_impl
!> Getter for the private 'weight' component
!! @return Weight of the connection (type real)
function get_weight_impl(this) result (weight)
class(connection_t), intent(in) :: this
real :: weight
......@@ -240,15 +260,22 @@ module connection_m
!----------------!-------------------------------------------------------------------------
! Common methods !
!----------------!
subroutine init_components_impl(this, input_neuron, output_neuron, weight)
class(connection_t), intent(inout) :: this
type(neuron_t), pointer :: input_neuron
type(neuron_t), pointer :: output_neuron
real, intent(in) :: weight
!> Initializes the common connection_t class components
!! 'input_neuron', 'output_neuron' and 'weight'.
!! I.e. serves similarly to an abstract constructor.
!! @param[in] input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param[in] output_neuron Pointer to the output neuron (instance of neuron_t)
!! @param[in] weight Weight of the connection (real number)
subroutine connection_init_components_impl(this, input_neuron, output_neuron, weight)
class(connection_t), intent(inout) :: this
class(neuron_t), pointer :: input_neuron
class(neuron_t), pointer :: output_neuron
real, intent(in) :: weight
#ifdef TIME_PROFILING
real :: start_time
call time_profiling_start(start_time);
call time_profiling_start(start_time)
#endif
this%input_neuron => input_neuron
......@@ -256,10 +283,13 @@ module connection_m
this%weight = weight
#ifdef TIME_PROFILING
call time_profiling_stop(start_time, 'init_components_impl');
call connection_time_profiling_stop(start_time, 'connection_init_components_impl')
#endif
end subroutine init_components_impl
end subroutine connection_init_components_impl
!> Nullifies pointers to input and output neurons, so they
!! don't get destroyed when the connection_t instance is
!! deallocated.
subroutine nullify_pointers_impl(this)
class(connection_t), intent(inout) :: this
#ifdef TIME_PROFILING
......@@ -273,6 +303,9 @@ module connection_m
#endif
end subroutine nullify_pointers_impl
!> Adds a given value to the current weight of the
!! connection.
!! @param[in] added_value Number (real) to be added to the current weight
subroutine adjust_weight_impl(this, added_value)
class(connection_t), intent(inout) :: this
real, intent(in) :: added_value
......@@ -286,13 +319,16 @@ module connection_m
#endif
end subroutine adjust_weight_impl
!> Passes (assigns) the product
!! input neuron state * weight)
!! to an output neuron.
subroutine pass_signal_impl(this)
class(connection_t), intent(in) :: this
#ifdef TIME_PROFILING
real :: start_time
call time_profiling_start(start_time)
#endif
call this%output_neuron%set_state(this%input_neuron%get_state() * this%weight)
call this%output_neuron%adjust_potential(this%input_neuron%get_state() * this%weight)
#ifdef TIME_PROFILING
call time_profiling_stop(start_time, 'pass_signal_impl')
#endif
......@@ -301,35 +337,28 @@ module connection_m
!-----------------------------!
! class interval_connection_t !
!-----------------------------!
subroutine pass_signal_interval_impl(this)
class(interval_connection_t), intent(in) :: this
#ifdef TIME_PROFILING
real :: start_time
call time_profiling_start(start_time)
#endif
call this%output_neuron%set_state(this%input_neuron%get_state() * this%weight)
#ifdef TIME_PROFILING
call time_profiling_stop(start_time, 'pass_signal_interval_impl')
#endif
end subroutine pass_signal_interval_impl
!--------------!------------------------------------------------------------------------
! Constructors !
!--------------!
!> Constructor of interval_connection_t class
!! @param[in] input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param[in] output_neuron Pointer to the output neuron (instance of neuron_t)
function new_interval_connection_2(input_neuron, output_neuron) result(new_obj)
type(neuron_t), pointer :: input_neuron
type(neuron_t), pointer :: output_neuron
class(neuron_t), pointer :: input_neuron
class(neuron_t), pointer :: output_neuron
real :: weight
type(interval_connection_t), pointer :: new_obj
integer :: values(8)
#ifdef TIME_PROFILING
real :: start_time
call time_profiling_start(start_time)
#endif
allocate(new_obj)
! todo change to random numbers from Gaussian distribution
call random_seed()
call random_number(weight)
call date_and_time(values=values)
weight = r4_normal_01(values(8))
call new_obj%init_components(input_neuron, output_neuron, weight)
#ifdef TIME_PROFILING
......@@ -337,9 +366,13 @@ module connection_m
#endif
end function new_interval_connection_2
!> Constructor of interval_connection_t class
!! @param[in] input_neuron Pointer to the input neuron (instance of neuron_t)
!! @param[in] output_neuron Pointer to the output neuron (instance of neuron_t)
!! @param[in] weight Weight of the connection (real number)
function new_interval_connection_3(input_neuron, output_neuron, weight) result(new_obj)
type(neuron_t), pointer :: input_neuron
type(neuron_t), pointer :: output_neuron
class(neuron_t), pointer :: input_neuron
class(neuron_t), pointer :: output_neuron
real, intent(in) :: weight
type(interval_connection_t), pointer :: new_obj
#ifdef TIME_PROFILING
......@@ -354,6 +387,26 @@ module connection_m
#endif
end function new_interval_connection_3
!----------------!---------------------------------------------------------------------
! Common methods !
!----------------!
!> Passes (assigns) the product
!! input neuron state * weight)
!! to an output neuron.
!! @todo Rewrite implementation to "interval"
subroutine pass_signal_interval_impl(this)
class(interval_connection_t), intent(in) :: this
#ifdef TIME_PROFILING
real :: start_time
call time_profiling_start(start_time)
#endif
!todo dopsat metodu pro interval
call this%output_neuron%adjust_potential(this%input_neuron%get_state() * this%weight)
#ifdef TIME_PROFILING
call time_profiling_stop(start_time, 'pass_signal_interval_impl')
#endif
end subroutine pass_signal_interval_impl
end module connection_m
program connection_mem_leak_test
use connection_m
use neuron_dummy_m
use neuron_m
use normal_m
type(neuron_t), target :: n1
type(neuron_t), target :: n2
type(mock_neuron_t), target :: n1
type(mock_neuron_t), target :: n2
type(neuron_t), pointer :: n1_p
type(neuron_t), pointer :: n2_p
type(neuron_t), pointer :: dummy_p
type(mock_neuron_t), pointer :: n1_p
type(mock_neuron_t), pointer :: n2_p
type(mock_neuron_t), pointer :: dummy_p
type(interval_connection_t), pointer :: con1, con2
......@@ -17,14 +17,8 @@ program connection_mem_leak_test
print *, '+---------------------------------------------------------+'
print *, 'Creating instances of the class neuron_t...'
n1 = neuron_t(21.3)
n2 = neuron_t(13.7)
print *, 'neuron_t instances were created successfully.'
print *, 'Assigning instances to pointer...'
n1_p => n1
n2_p => n2
print *, 'Assignment was successful.'
n1_p => mock_neuron_t()
n2_p => mock_neuron_t()
print *, 'Creating an instance of the class interval_connection_t with 3-parameters constructor...'
con1 => interval_connection_t(input_neuron=n1_p, &
......
module neuron_dummy_m
implicit none
public
! TODO smazat
!> neuron class
type :: neuron_t
real :: state
contains
procedure :: get_state => get_state_impl
procedure :: set_state => set_state_impl
end type neuron_t
contains
!--------------!
! class neuron_t !
!--------------!
! TODO smazat
function get_state_impl(this) result(state)
class(neuron_t), intent(in) :: this
real :: state
state = this%state
end function get_state_impl
! TODO smazat
subroutine set_state_impl(this, new_state)
class(neuron_t), target :: this
real, intent(in) :: new_state
this%state = new_state
end subroutine set_state_impl
end module
!> Module containing classes representing neurons
!! in neural networks.
!!
!! It uses 'time_measurement_m' module.
!!
!! @author Martin Beseda
!! @author Martin Mrovec
!! @date 2017
!! @todo Write constructors for classes!
module neuron_m
use time_measurement_m
implicit none
public
!----------------!------------------------------------------------------------------------------
! class neuron_t !
!----------------!
!> Abstract class representing a general neuron
type, abstract :: neuron_t
private
real :: potential !< Neuron inner potential
real :: state !< State of the neuron (0/1 for binary n. etc.)
!> Parent interconnection - to check, if all inputs have already been accepted
!! @todo move to connection_t
!class(interconnection_t), pointer :: parent_interconnection
integer :: id !< Neuron ID
contains
!> Initalizes the common neuron_t classes components
!! ('potential' to 0, 'state' to 0)
procedure, private :: init_components => neuron_init_components_impl
!> Adds the input signal value to the current potential
!! @param[in] input_signal Input value
procedure :: adjust_potential => adjust_potential_impl
!> Performs the activation function and stores the result into the 'state' component
procedure(activate_int), private, deferred :: activate
!> Getter to the 'potential' component
!! @return Value of the neuron's potential (real number)
procedure :: get_potential => get_potential_impl
!> Getter to the 'state' component
!! @return Value of the current neuron's state
procedure :: get_state => get_state_impl
!> Getter to the 'id' component
!! @return Neuron ID
procedure :: get_id => get_id_impl
!> Getter to the 'parent_interconnection'
!! @return Pointer to the parent interconnetion instance
!! @todo move to connection_t class!
!procedure :: get_parent_interconnection => get_parent_interconnection_impl
end type neuron_t
abstract interface
subroutine activate_int(this)
!> Interface for the deferred (i.e. abstract) method 'activate' of the clas neuron_t
import neuron_t
class(neuron_t), intent(inout) :: this
end subroutine activate_int
end interface
!---------------------!------------------------------------------------------------------------
! class mock_neuron_t !
!---------------------!
!> Mock neuron_t class
type, extends(neuron_t) :: mock_neuron_t
contains
!> Mock method, does nothing - it's only purpose is to override the deffered one
procedure :: activate => mock_activate_impl
!> Getter to the 'potential' component
!! @return Number 5.0
procedure :: get_potential => mock_get_potential_impl
!> Getter to the 'state' component
!! @return Number 15.0
procedure :: get_state => mock_get_state_impl
end type mock_neuron_t
interface mock_neuron_t
!> Constructor of mock_neuron_t class
module procedure :: new_mock_neuron
end interface mock_neuron_t
!-----------------------!----------------------------------------------------------------------
! class binary_neuron_t !
!-----------------------!
!> Binary neuron class - uses unit-step as the activation function
!! @todo write constructor with random init of threshold
type, extends(neuron_t) :: binary_neuron_t
private
real :: threshold !< When neuron potential exceeds this value, neuron becomes excited
contains
!> Activation function - transforms potential into the output state value
!! AND assigns it into the 'state' component
!!
!! Unit-step function - (returns 1 for potential > threshold, otherwise returns 0)
procedure, private :: activate => unit_step_activate_impl
end type binary_neuron_t
!-----------------------!----------------------------------------------------------------------
! class linear_neuron_t !
!-----------------------!
!> Linear neuron class - returns its potential as the output of the activation function
type, extends(neuron_t) :: linear_neuron_t
contains
!> Activation function - just returns the neuron's potential value
procedure, private :: activate => identity_potential_activate_impl
end type linear_neuron_t
!--------------------------!-------------------------------------------------------------------
! class sigmoidal_neuron_t !
!--------------------------!
!> Sigmoidal neuron class - uses sigmoid as an activation function
type, extends(neuron_t) :: sigmoidal_neuron_t
contains
!> Activation function - sigmoid
procedure, private :: activate => sigmoid_activate_impl
end type sigmoidal_neuron_t
contains
!------------------------!---------------------------------------------------------------------
! Method implementations !