Last active
June 5, 2018 11:11
-
-
Save misgeatgit/28bf27781a6106b021d68c34fa73ba22 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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