<commit_before>/*
 * CocircConn.cpp
 *
 *  Created on: Nov 10, 2008
 *      Author: rasmussn
 */

#include "GeislerConn.hpp"
#include "../io/io.h"
#include "../utils/conversions.h"
#include "../include/pv_types.h"
#include <assert.h>
#include <string.h>
#include <float.h>

namespace PV {

GeislerConn::GeislerConn()
{
   printf("GeislerConn::GeislerConn: running default constructor\n");
   initialize_base();
}

GeislerConn::GeislerConn(const char * name, HyPerCol * hc, HyPerLayer * pre,
      HyPerLayer * post, int channel)
{
   initialize_base();
   initialize(name, hc, pre, post, channel);
}

GeislerConn::GeislerConn(const char * name, HyPerCol * hc, HyPerLayer * pre,
      HyPerLayer * post)
{
   initialize_base();
   initialize(name, hc, pre, post, channel, NULL); // use default channel
}

// provide filename or set to NULL
GeislerConn::GeislerConn(const char * name, HyPerCol * hc, HyPerLayer * pre,
      HyPerLayer * post, int channel, const char * filename)
{
   initialize_base();
   initialize(name, hc, pre, post, channel, filename);
}

int GeislerConn::initialize_base()
{
   numUpdates = 0;
   avePreActivity = NULL;
   avePostActivity = NULL;
   geislerPatches = NULL;
   return KernelConn::initialize_base();
}


PVPatch ** GeislerConn::createWeights(PVPatch ** patches, int nPatches, int nxPatch,
      int nyPatch, int nfPatch)
{
   patches = KernelConn::createWeights(patches, nPatches, nxPatch, nyPatch, nfPatch);
   PVPatch ** kernel_patches = this->kernelPatches;

   const int arbor = 0;
   int num_geisler_patches = numDataPatches(arbor);

   avePreActivity = (pvdata_t *) calloc(sizeof(pvdata_t), num_geisler_patches);
   avePostActivity = (pvdata_t *) calloc(sizeof(pvdata_t), num_geisler_patches);

   assert(geislerPatches == NULL);
   geislerPatches = (PVPatch**) calloc(sizeof(PVPatch*), num_geisler_patches);
   assert(geislerPatches != NULL);

   for (int geislerIndex = 0; geislerIndex < num_geisler_patches; geislerIndex++) {
      geislerPatches[geislerIndex] = pvpatch_inplace_new(nxPatch, nyPatch, nfPatch);
      assert(geislerPatches[geislerIndex] != NULL );
   }

   return patches;
}

int GeislerConn::deleteWeights()
{
   const int arbor = 0;

   for (int k = 0; k < numDataPatches(arbor); k++) {
      pvpatch_inplace_delete(geislerPatches[k]);
   }
   free(geislerPatches);
   free(avePreActivity);
   free(avePostActivity);

   return KernelConn::deleteWeights();
}

PVPatch ** GeislerConn::initializeDefaultWeights(PVPatch ** patches, int numPatches)
{
   // patches should already be initialized to zero
   return patches;
}


int GeislerConn::updateState(float time, float dt)
{
   PVPatch ** kernel_patches = this->kernelPatches;
   int axonID = 0;
   int num_kernels = this->numDataPatches(axonID);
   numUpdates++;

   int nPreEx = pre->clayer->numExtended;
   const pvdata_t * aPre = pre->getLayerData();
   for (int kfPre = 0; kfPre < num_kernels; kfPre++){
      pvdata_t avePre = 0.0;
      for (int kPre = 0; kPre < nPreEx; kPre+=num_kernels){
         avePre += aPre[kPre] > 0 ? aPre[kPre] : 0;
      }
      avePre *= num_kernels / (float) nPreEx ;
      avePreActivity[kfPre] += avePre;
   }

   int nPost = post->clayer->numNeurons;
   const pvdata_t * aPost = post->getLayerData();
   for (int kfPost = 0; kfPost < num_kernels; kfPost++){
      pvdata_t avePost = 0.0;
      for (int kPost = 0; kPost < nPost; kPost+=num_kernels) {
         PVLayerLoc loc = post->clayer->loc;
         int kPostEx = kIndexExtended(kPost, loc.nx, loc.ny, num_kernels, loc.nPad);
            avePost += aPost[kPostEx];
      }
      avePost *= num_kernels / (float) nPost ;
      avePostActivity[kfPost] += avePost;
   }

   // initialize geislerPatches
   int numWeights = nxp * nyp * nfp;
   for (int iKernel = 0; iKernel < num_kernels; iKernel++){
      pvdata_t * kernelWeights = kernelPatches[iKernel]->data;
      pvdata_t * geislerWeights = geislerPatches[iKernel]->data;
      for (int iWeight = 0; iWeight < numWeights; iWeight++){
         kernelWeights[iWeight] = geislerWeights[iWeight];
         geislerWeights[iWeight] = 0.0;
      }
   }

   int status = updateWeights(axonID);

   // normalize geislerPatches
   for (int iKernel = 0; iKernel < num_kernels; iKernel++){
      pvdata_t * kernelWeights = kernelPatches[iKernel]->data;
      pvdata_t * geislerWeights = geislerPatches[iKernel]->data;
      for (int iWeight = 0; iWeight < numWeights; iWeight++){
         geislerWeights[iWeight] /= nPost;
         geislerWeights[iWeight] += kernelWeights[iWeight];
#ifdef APPLY_GEISLER_WEIGHTS
         int kfPost = iWeight % num_kernels;
         kernelWeights[iWeight] /= numUpdates;
         pvdata_t kernelNorm =
            (avePreActivity[iKernel] / numUpdates ) * (avePostActivity[kfPost] / numUpdates );
//         kernelWeights[iWeight] -= kernelNorm;
#else
         kernelWeights[iWeight] = 0.0;
#endif
      }
   }
#ifdef APPLY_GEISLER_WEIGHTS
   this->normalizeWeights(this->kernelPatches, this->numDataPatches(axonID));
#endif
   return status;
}


int GeislerConn::updateWeights(int axonID)
{
   pvdata_t aPreThresh = 0.0f;
   pvdata_t aPostThresh = 0.0f;

   // this stride is in extended space for post-synaptic activity and
   // STDP decrement variable
   int postStrideY = post->clayer->numFeatures
   * (post->clayer->loc.nx + 2 * post->clayer->loc.nPad);

   int num_pre_extended = pre->clayer->numExtended;
   assert(num_pre_extended == numWeightPatches(axonID));

   const pvdata_t * preLayerData = pre->getLayerData();

#define TRAINING_G1_TRIALS
#ifdef TRAINING_G1_TRIALS
<commit_msg>added note regarding inconsistency of global threshold method for MPI runs<commit_after>/*
 * CocircConn.cpp
 *
 *  Created on: Nov 10, 2008
 *      Author: rasmussn
 */

#include "GeislerConn.hpp"
#include "../io/io.h"
#include "../utils/conversions.h"
#include "../include/pv_types.h"
#include <assert.h>
#include <string.h>
#include <float.h>

namespace PV {

GeislerConn::GeislerConn()
{
   printf("GeislerConn::GeislerConn: running default constructor\n");
   initialize_base();
}

GeislerConn::GeislerConn(const char * name, HyPerCol * hc, HyPerLayer * pre,
      HyPerLayer * post, int channel)
{
   initialize_base();
   initialize(name, hc, pre, post, channel);
}

GeislerConn::GeislerConn(const char * name, HyPerCol * hc, HyPerLayer * pre,
      HyPerLayer * post)
{
   initialize_base();
   initialize(name, hc, pre, post, channel, NULL); // use default channel
}

// provide filename or set to NULL
GeislerConn::GeislerConn(const char * name, HyPerCol * hc, HyPerLayer * pre,
      HyPerLayer * post, int channel, const char * filename)
{
   initialize_base();
   initialize(name, hc, pre, post, channel, filename);
}

int GeislerConn::initialize_base()
{
   numUpdates = 0;
   avePreActivity = NULL;
   avePostActivity = NULL;
   geislerPatches = NULL;
   return KernelConn::initialize_base();
}


PVPatch ** GeislerConn::createWeights(PVPatch ** patches, int nPatches, int nxPatch,
      int nyPatch, int nfPatch)
{
   patches = KernelConn::createWeights(patches, nPatches, nxPatch, nyPatch, nfPatch);
   PVPatch ** kernel_patches = this->kernelPatches;

   const int arbor = 0;
   int num_geisler_patches = numDataPatches(arbor);

   avePreActivity = (pvdata_t *) calloc(sizeof(pvdata_t), num_geisler_patches);
   avePostActivity = (pvdata_t *) calloc(sizeof(pvdata_t), num_geisler_patches);

   assert(geislerPatches == NULL);
   geislerPatches = (PVPatch**) calloc(sizeof(PVPatch*), num_geisler_patches);
   assert(geislerPatches != NULL);

   for (int geislerIndex = 0; geislerIndex < num_geisler_patches; geislerIndex++) {
      geislerPatches[geislerIndex] = pvpatch_inplace_new(nxPatch, nyPatch, nfPatch);
      assert(geislerPatches[geislerIndex] != NULL );
   }

   return patches;
}

int GeislerConn::deleteWeights()
{
   const int arbor = 0;

   for (int k = 0; k < numDataPatches(arbor); k++) {
      pvpatch_inplace_delete(geislerPatches[k]);
   }
   free(geislerPatches);
   free(avePreActivity);
   free(avePostActivity);

   return KernelConn::deleteWeights();
}

PVPatch ** GeislerConn::initializeDefaultWeights(PVPatch ** patches, int numPatches)
{
   // patches should already be initialized to zero
   return patches;
}


int GeislerConn::updateState(float time, float dt)
{
   PVPatch ** kernel_patches = this->kernelPatches;
   int axonID = 0;
   int num_kernels = this->numDataPatches(axonID);
   numUpdates++;

   int nPreEx = pre->clayer->numExtended;
   const pvdata_t * aPre = pre->getLayerData();
   for (int kfPre = 0; kfPre < num_kernels; kfPre++){
      pvdata_t avePre = 0.0;
      for (int kPre = 0; kPre < nPreEx; kPre+=num_kernels){
         avePre += aPre[kPre] > 0 ? aPre[kPre] : 0;
      }
      avePre *= num_kernels / (float) nPreEx ;
      avePreActivity[kfPre] += avePre;
   }

   int nPost = post->clayer->numNeurons;
   const pvdata_t * aPost = post->getLayerData();
   for (int kfPost = 0; kfPost < num_kernels; kfPost++){
      pvdata_t avePost = 0.0;
      for (int kPost = 0; kPost < nPost; kPost+=num_kernels) {
         PVLayerLoc loc = post->clayer->loc;
         int kPostEx = kIndexExtended(kPost, loc.nx, loc.ny, num_kernels, loc.nPad);
            avePost += aPost[kPostEx];
      }
      avePost *= num_kernels / (float) nPost ;
      avePostActivity[kfPost] += avePost;
   }

   // initialize geislerPatches
   int numWeights = nxp * nyp * nfp;
   for (int iKernel = 0; iKernel < num_kernels; iKernel++){
      pvdata_t * kernelWeights = kernelPatches[iKernel]->data;
      pvdata_t * geislerWeights = geislerPatches[iKernel]->data;
      for (int iWeight = 0; iWeight < numWeights; iWeight++){
         kernelWeights[iWeight] = geislerWeights[iWeight];
         geislerWeights[iWeight] = 0.0;
      }
   }

   int status = updateWeights(axonID);

   // normalize geislerPatches
   for (int iKernel = 0; iKernel < num_kernels; iKernel++){
      pvdata_t * kernelWeights = kernelPatches[iKernel]->data;
      pvdata_t * geislerWeights = geislerPatches[iKernel]->data;
      for (int iWeight = 0; iWeight < numWeights; iWeight++){
         geislerWeights[iWeight] /= nPost;
         geislerWeights[iWeight] += kernelWeights[iWeight];
#ifdef APPLY_GEISLER_WEIGHTS
         int kfPost = iWeight % num_kernels;
         kernelWeights[iWeight] /= numUpdates;
         pvdata_t kernelNorm =
            (avePreActivity[iKernel] / numUpdates ) * (avePostActivity[kfPost] / numUpdates );
//         kernelWeights[iWeight] -= kernelNorm;
#else
         kernelWeights[iWeight] = 0.0;
#endif
      }
   }
#ifdef APPLY_GEISLER_WEIGHTS
   this->normalizeWeights(this->kernelPatches, this->numDataPatches(axonID));
#endif
   return status;
}


int GeislerConn::updateWeights(int axonID)
{
   pvdata_t aPreThresh = 0.0f;
   pvdata_t aPostThresh = 0.0f;

   // this stride is in extended space for post-synaptic activity and
   // STDP decrement variable
   int postStrideY = post->clayer->numFeatures
   * (post->clayer->loc.nx + 2 * post->clayer->loc.nPad);

   int num_pre_extended = pre->clayer->numExtended;
   assert(num_pre_extended == numWeightPatches(axonID));

   const pvdata_t * preLayerData = pre->getLayerData();

   //TODO! following method is not MPI compatible (gives different answers depending on partition)
#define TRAINING_G1_TRIALS
#ifdef TRAINING_G1_TRIALS

{'fraction_non_alphanumeric': 0.12281167108753316, 'fraction_numerical': 0.00654288240495137, 'mean_word_length': 3.7070328755722013, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3807394', 'n_tokens_mistral': 4160, 'n_tokens_neox': 3992, 'n_words': 857}