Skip to content

Instantly share code, notes, and snippets.

@misgeatgit
Last active June 5, 2018 11:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save misgeatgit/28bf27781a6106b021d68c34fa73ba22 to your computer and use it in GitHub Desktop.
Save misgeatgit/28bf27781a6106b021d68c34fa73ba22 to your computer and use it in GitHub Desktop.
diff --git a/opencog/attention/ImportanceDiffusionBase.cc b/opencog/attention/ImportanceDiffusionBase.cc
index 850818f..23f6244 100644
--- a/opencog/attention/ImportanceDiffusionBase.cc
+++ b/opencog/attention/ImportanceDiffusionBase.cc
@@ -131,35 +131,6 @@ void ImportanceDiffusionBase::diffuseAtom(Handle source)
AttentionValue::sti_t totalDiffusionAmount =
calculateDiffusionAmount(source);
-#ifdef LOG_AV_STAT
- // Log sti gain from spreading via non-hebbian links
- for(const auto& kv : probabilityVectorIncident){
- if(atom_avstat.find(kv.first) == atom_avstat.end()){
- AVStat avstat;
- avstat.link_sti_gain = kv.second;
- atom_avstat[kv.first] = avstat;
- }
- atom_avstat[kv.first].link_sti_gain += kv.second;
- }
-
- // Log sti gain from spreading via hebbian links
- for(const auto& kv : probabilityVectorHebbianAdjacent){
- if(atom_avstat.find(kv.first) == atom_avstat.end()){
- AVStat avstat;
- avstat.heblink_sti_gain = kv.second;
- atom_avstat[kv.first] = avstat;
- }
- atom_avstat[kv.first].heblink_sti_gain += kv.second;
- }
-
- // Log amount of sti spread from
- if(atom_avstat.find(source) == atom_avstat.end()){
- AVStat avstat;
- avstat.spreading = totalDiffusionAmount;
- atom_avstat[source] = avstat;
- }
- atom_avstat[source].spreading += totalDiffusionAmount;
-#endif
#ifdef DEBUG
std::cout << "Total diffusion amount: " << totalDiffusionAmount << std::endl;
@@ -184,9 +155,14 @@ void ImportanceDiffusionBase::diffuseAtom(Handle source)
// Redistribute sti values that should not go to types in hsFilterOut.
std::map<Handle, double> refund;
+ double remaining_sti = 0;
for(auto it = probabilityVector.begin() ; it !=probabilityVector.end() ; ++it){
std::vector<std::pair<Handle, double>> tempRefund;
- redistribute(it->first, it->second, tempRefund);
+ auto r = redistribute(it->first, it->second, tempRefund);
+ if( r != 0){
+ remaining_sti += r;
+ continue;
+ }
// Now lets append the tempRefund map to refund map
for(const auto& p : tempRefund){
if(refund.find(p.first) == refund.end())
@@ -196,9 +172,44 @@ void ImportanceDiffusionBase::diffuseAtom(Handle source)
}
}
+ // Divide STIs not distributed.
+ double per_atom = remaining_sti/ refund.size();
+ for(auto& p : refund)
+ p.second += per_atom;
+
// Finishe the redistribution by assigning new values to probabilityVector.
probabilityVector = refund;
-
+
+#ifdef LOG_AV_STAT
+ // Log sti gain from spreading via non-hebbian links
+ for(const auto& kv : probabilityVectorIncident){
+ if(atom_avstat.find(kv.first) == atom_avstat.end()){
+ AVStat avstat;
+ avstat.link_sti_gain = kv.second;
+ atom_avstat[kv.first] = avstat;
+ }
+ atom_avstat[kv.first].link_sti_gain += kv.second;
+ }
+
+ // Log sti gain from spreading via hebbian links
+ for(const auto& kv : probabilityVectorHebbianAdjacent){
+ if(atom_avstat.find(kv.first) == atom_avstat.end()){
+ AVStat avstat;
+ avstat.heblink_sti_gain = kv.second;
+ atom_avstat[kv.first] = avstat;
+ }
+ atom_avstat[kv.first].heblink_sti_gain += kv.second;
+ }
+
+ // Log amount of sti spread from
+ if(atom_avstat.find(source) == atom_avstat.end()){
+ AVStat avstat;
+ avstat.spreading = totalDiffusionAmount;
+ atom_avstat[source] = avstat;
+ }
+ atom_avstat[source].spreading += totalDiffusionAmount;
+#endif
+
// Perform diffusion from the source to each atom target
for( const auto& p : probabilityVector)
{
@@ -535,43 +546,47 @@ void ImportanceDiffusionBase::processDiffusionStack()
}
/**
- * Redistributed amount of sti that should have gone to target atom if
- * the atom type is in the Fitler set. The sti will be equally distributed
- * to the incoming or outgoing set of target atom.
+ * Redistribute amount of sti that should have gone to target atom if
+ * the atom type wasn't in the FitlerOut list. The sti will be equally distributed
+ * to the all neighboring atoms. if any of the atoms are invalid types, the
+ * amount they were supposed to receive will be recursively redistributed untill
+ * it reaches the maximum allowed traversal depth.
*
* @param target the atom whose to type is to be checked against the filter set.
- *
- * @sti the sti that should be redistribited if the target's type is in Filter
+ * @param sti the sti that should be redistribited if the target's type is in Filter
* set.
+ * @param refund a list of pairs of atoms and redistributed sti.
+ * @param depth the current depth of the traversing.
*
- * @refund a list of pairs of atoms and redistributed sti.
- *
- * @return void.
+ * @return 0 on successfull redistribution or @param sti on failure to do so
+ * before depth reaches maximum allowable value.
*
*/
-void ImportanceDiffusionBase::redistribute(const Handle& target, const double& sti,
- std::vector<std::pair<Handle, double>>& refund){
- static unsigned int NRECURSION = 1; // Prevent stack-overflowing. XXX how to determing maxdepth?
- auto ij = std::find_if(hsFilterOut.begin(), hsFilterOut.end(),
+double ImportanceDiffusionBase::redistribute(const Handle& target, const double& sti,
+ std::vector<std::pair<Handle, double>>& refund
+ ,unsigned int depth/*=0*/){
+ auto it = std::find_if(hsFilterOut.begin(), hsFilterOut.end(),
[target](const Handle& h){
- return (target->get_type() == classserver().getType(h->get_name()));
+ return (target->get_type() == nameserver().getType(h->get_name()));
});
-
- if(ij != hsFilterOut.end()){
- // This is to prevent indefinite recursion which could
- // happen incase of a cyclic graph.
- // Assuming MIN_SPREADING_VALUE will be very small
- // compared to the minimum STI in the AF and no direct stimulation,
- // this atoms should never get the chance to enter into the AF.
- // the remaining value(sti) should in theory be collected back by rent collection
- // agent.
- // FIXME it could accumulate such small sti values over time and endup in the AF?
+ double not_redistributed = 0;
+ // If target is a type in the hsFilterOut list, redistribute sti to
+ // neighbors.
+ if(hsFilterOut.end() != it){
+ // If STI to be distributed is smaller than the af boundary or the
+ // recursion has reached maximum depth allowed, assign the sti to
+ // the last atom in refund vector and return 0 balance. If the refund
+ // vector is empty, return the sti itself.
auto min_spreading_value = _bank->get_af_min_sti();
- if(sti < min_spreading_value or NRECURSION > 100){
- refund.push_back(std::make_pair(target, sti));
- return;
+ // TODO define a parameter for the maximum depth?
+ if(sti < min_spreading_value or depth > 20){
+ if(not refund.empty()){
+ refund[refund.size()-1].second += sti;
+ return 0;
+ } else{
+ return sti;
+ }
}
-
// Redistribute to all neighbors.
HandleSeq seq;
if(target->is_link())
@@ -579,14 +594,27 @@ void ImportanceDiffusionBase::redistribute(const Handle& target, const double& s
target->getIncomingSet(std::back_inserter(seq));
- auto r = sti/seq.size();
+ size_t spreaded_to = 0; // Number of atoms visited.
+ // Equally divide sti to neighbors.
+ double dividened = sti/(double)seq.size();
for(const Handle& h : seq)
- redistribute(h, r, refund);
+ {
+ ++spreaded_to;
+ double balance = redistribute(h, dividened, refund, depth+1);
+ // Adjust dividened if sti isn't spread to this atom.
+ if( balance > 0){
+ // If the last one failed. return amount not distributed.
+ if( spreaded_to == seq.size()){
+ not_redistributed = balance;
+ break;
+ }
+ dividened += (balance / ( seq.size() - spreaded_to));
+ }
+ }
}
else{
refund.push_back(std::make_pair(target, sti));
}
- ++NRECURSION;
- return;
+ return not_redistributed;
}
diff --git a/opencog/attention/ImportanceDiffusionBase.h b/opencog/attention/ImportanceDiffusionBase.h
index da6150f..7013e05 100644
--- a/opencog/attention/ImportanceDiffusionBase.h
+++ b/opencog/attention/ImportanceDiffusionBase.h
@@ -93,8 +93,8 @@ protected:
// Recursively try to redistribute STI which was supposed to be delivered to
// certain atom types which should not receive STI.
- void redistribute(const Handle& target, const double& sti, std::vector<std::pair<Handle,
- double>>& refund);
+ double redistribute(const Handle& target, const double& sti, std::vector<std::pair<Handle,
+ double>>& refund, unsigned int depth = 0);
public:
ImportanceDiffusionBase(CogServer&);
virtual ~ImportanceDiffusionBase();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment