head	1.3;
access;
symbols;
locks; strict;
comment	@ * @;


1.3
date	94.08.29.04.19.54;	author rjj;	state Exp;
branches;
next	1.2;

1.2
date	94.07.01.20.31.09;	author rjj;	state Exp;
branches;
next	1.1;

1.1
date	94.07.01.01.18.05;	author rjj;	state Exp;
branches;
next	;


desc
@Initial implementation for the Hopfield Neural Network algorithm.  Buggy!
@


1.3
log
@Modified include stmts to be iac++ 2.0 compliant
@
text
@// hopfield-weights.c   Section: 13.2, Hopfield
//      Copyright 1994, Center for Computer Vision and Visualization,
//      University of Florida.  All rights reserved.
// Here we define some functions that will support the Hopfield algorithm.
//
// The goal here is to define functions necessary to build the 
//      weighting image utilized in the Hopfiled nueral network.
// We will do that by a set of transformations from the examplar
//      images to the final weighting image.
// The advantage of building this image, is that the template
//      used in the Hopfiedl algorithm, even though it is variant,
//      can use the weighting image to construct the template image.
//


#include "Nbh.h"
#include "DDTempl.h"
#include "IntConv.h"
#include "hopfield-weights.h"
#include "make-examplars.h"


void im_stats( const char *str,
	       const IA_Image<IA_Point<int>,int> & im ) {
    cerr << "\n" << __FILE__ << "::" << str
	 << "\n\tmin   = " << min(im)
	 << "   max   = " << max(im)
	 << "   inf() = " << im.domain().inf()
	 << "   sup() = " << im.domain().sup()
	 << endl;
}



/////////////////////////////////////////////////////////////////////////
// ek_image_func()
// This function returns a image to be used in a convolution with
//    the 2D e_image to construct the 3D ek_image.
// It is given a 3D point <k,i,j>, and returns a 2D
//    image which will reference the e[k][i] & e[k][j] points
//    in the e_image.
// Where i != j, it returns a 2 point image, with image value 1.
// Where i == j, it returns a 1 point image, with image value 0.
//
IA_Image<IA_Point<int>,int>
ek_image_func( const IA_Point<int> & p3d ) {

    int k = p3d(0), i = p3d(1), j = p3d(2);
    if ( i == j ) {
	return
	    IA_Image<IA_Point<int>,int>(
		IA_Set<IA_Point<int> >( IA_Point<int>( 0, 0 ) ), // e<k,i>
		0 );
    }
    // i != j
    return
	IA_Image<IA_Point<int>,int>(
	    IA_Set<IA_Point<int> >( IA_Point<int>( 0, 0 ) )    // e<k,i>
	    | IA_Set<IA_Point<int> >( IA_Point<int>( 0, j-i ) ), // e<k,j>
	    1 );
}


/////////////////////////////////////////////////////////////////////////
// ek_circle()
// This is the weighting function used in the generic_convolution with
//    the ek_image.  We simply do multiplication.
//
int ek_circle( int v1, int v2 ) {
    return v1 * v2;
}


/////////////////////////////////////////////////////////////////////////
// ek_gamma()
// This is the pairwise reduction function for use in the 
//    generic_convolution with the ek_image.
// NOTE: For this case this function is exactly the same as ek_circle()
//    however, in general, this is not the case.
//
int ek_gamma( int v1, int v2 ) {
    return v1 * v2;
}


static int weight_template_image_K;
IA_Image<IA_Point<int>,int>
weight_template_image( const IA_Point<int> & p ) {
    // Ignore the point and always return the same image
    int K = weight_template_image_K;
    return
	IA_Image<IA_Point<int>,int>(
	    IA_boxy_pset( IA_Point<int>(   0, 0, 0 ),
			  IA_Point<int>( K-1, 0, 0 ) ),
	    1 );
}



/////////////////////////////////////////////////////////////////////////
// hopfield_weight_image()
// This function creates the weighting image as defined by the
//    Hopfield algorithm, based on the examplar images.
//
IA_Image<IA_Point<int>,int>
hopfield_weight_image( IA_Image<IA_Point<int>,int> * e_array,
		       unsigned int e_array_size )
{
    IA_Image<IA_Point<int>,int>
	e_image( make_examplars_image( e_array, e_array_size ) );

    im_stats( "e_image", e_image );

    // Construct a 3D image of size KxNxN by convolution of the
    //   2D e_image and a variant template with the properties:
    //        3D coordinate: <k,i,j>
    //        i == j  => domain is {<0,0>} value is 0
    //        i != j  => domain is {<0,0>,<0,j-i>} value is 1
    // NOTE: This could not be done with a variant Neighborhood product
    //   reduction, even if variant nbhd\'s were supported in iac++,
    //   because the weight factor differs.  It would be possible if
    //   a vector reduction was used that zeturned 0 if vector length
    //   was 1
    unsigned int
	K = e_array_size,
	N = e_array[0].domain().card();

    IA_Set<IA_Point<int> >
	ek_ps( IA_boxy_pset( IA_Point<int>(   0,   0,   0 ),
			     IA_Point<int>( K-1, N-1, N-1 ) ) ),
	weight_ps( IA_boxy_pset( IA_Point<int>(   0,   0 ),
				 IA_Point<int>( N-1, N-1 ) ) );

    IA_DDTemplate<IA_Image<IA_Point<int>,int> >
	ek_template( ek_ps, ek_image_func );

    int gamma_zero = 1, ring_zero = 1;
    IA_Image<IA_Point<int>,int>
	ek_image( generic_product( e_image,
				   ek_template,
				   ek_ps,      // destination ps
				   ek_circle,  // product reduction
				   ek_gamma,   // product reduction
				   gamma_zero,
				   ring_zero ) );

    im_stats( "ek_image", ek_image );

    // Now we can generate the weighting image as a Neighborhood
    //    reduction from a 3D image to a 2D image.
    // We are summing the values over points <k,i,j> where
    //    0<=k<K, the target in the weight image is <i,j>

#if 0
    IA_Neighborhood<IA_Point<int>,IA_Point<int> >
	w_nbhd( (unsigned int) 3,
		IA_boxy_pset( IA_Point<int>(   0, 0, 0 ),
			      IA_Point<int>( K-1, 0, 0 ) ) );

    IA_Image<IA_Point<int>,int>
	w_image( sum( ek_image, w_nbhd, weight_ps ) );
#elseif 0
    IA_DDTemplate<IA_Image<IA_Point<int>,int> >
	w_tmpl( 2,
		IA_Image<IA_Point<int>,int>(
		    IA_boxy_pset( IA_Point<int>(   0, 0, 0 ),
				  IA_Point<int>( K-1, 0, 0 ) ),
		    1 )
		);
		    

    IA_Image<IA_Point<int>,int>
	w_image( linear_product( ek_image, w_tmpl, weight_ps ) );
#else
    ::weight_template_image_K = K;
    IA_DDTemplate<IA_Image<IA_Point<int>,int> >
	w_tmpl( weight_ps, weight_template_image );

    IA_Image<IA_Point<int>,int>
	w_image( linear_product( ek_image, w_tmpl, weight_ps ) );
#endif

    im_stats( "w_image", w_image );

    return  w_image;
}
@


1.2
log
@Move make_examplars_image() to  make-examplars.[hc].
This makes this file pretty much obsolete.
@
text
@d1 1
a1 1
// hopfield-weights.c
d16 1
a16 1
#include "Neighborhood.h"
d18 1
a18 1
#include "IntConvolutions.h"
@


1.1
log
@Initial revision
@
text
@a15 1
#include "hopfield-weights.h"
d19 2
a32 39
/////////////////////////////////////////////////////////////////////////
// make_examplars_image()
// Create an 2D image from the array of 1D examplar images.
// We assume that each examplar image is the same cardinality.
//
IA_Image<IA_Point<int>,int>
make_examplars_image( IA_Image<IA_Point<int>,int> * e_array,
		      unsigned int e_array_size )
{
    // Remember the cardinality of each e_array image
    int e_card = e_array[0].domain().card();

    // Create the image we want to return
    IA_Image<IA_Point<int>,int>
	e_image( IA_boxy_pset( IA_Point<int>( 0, 0 ),
			       IA_Point<int>( e_array_size - 1,
					      e_card -1 ) ),
		 0 );

    // Map examplar image data into 2D e_im image data
    // We will declare the 1D and 2D points exactly once to avoid
    //    the overhead of re allocating them each time through a loop.
    IA_Point<int>
	p1d(0), // a 1D point
	p2d(0,0);

    for( int k=0; k<e_array_size; k++ ) {
	p2d[0] = k;
	for( int n=0; n<e_card; n++ ) {
	    p1d[0] = n;
	    p2d[1] = n;
	    e_image[ p2d ] = e_array[k]( p1d );
	}
    }

    // Return the new image
    return
	e_image;
}
@
