|
|
|
|
|
|
|
|
|
|
|
// snf_saccades.cpp
|
|
|
|
|
|
// Saccades engine adaptation for MessageSniffer
|
|
|
|
|
|
// Copyright 2014 MicroNeil Research Corporation (www.microneil.com)
|
|
|
|
|
|
// Licensed to ARM Research Labs for use in Message Sniffer.
|
|
|
|
|
|
|
|
|
|
|
|
#include <set>
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
#include "snf_saccades.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
|
|
bool doesOverlap(unsigned int workingStart, unsigned int testStart, unsigned int workingFinish) {
|
|
|
|
|
|
return(
|
|
|
|
|
|
testStart >= workingStart &&
|
|
|
|
|
|
testStart <= workingFinish
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
vector<saccade> saccades_engine::recall() {
|
|
|
|
|
|
vector<saccade> recollection;
|
|
|
|
|
|
int markersSize = markers.size();
|
|
|
|
|
|
if(0 < markersSize) {
|
|
|
|
|
|
set<saccade_marker>::iterator i;
|
|
|
|
|
|
recollection.reserve(markers.size());
|
|
|
|
|
|
bool isFirstPass = true;
|
|
|
|
|
|
unsigned int workingStart = 0;
|
|
|
|
|
|
unsigned int workingFinish = 0;
|
|
|
|
|
|
for(i = markers.begin(); i != markers.end(); i++) {
|
|
|
|
|
|
const saccade& theSaccade = (*i).theSaccade;
|
|
|
|
|
|
if(isFirstPass) {
|
|
|
|
|
|
workingStart = theSaccade.start;
|
|
|
|
|
|
workingFinish = theSaccade.finish;
|
|
|
|
|
|
isFirstPass = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
if(doesOverlap(workingStart, theSaccade.start, workingFinish)) {
|
|
|
|
|
|
workingFinish = theSaccade.finish;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
recollection.push_back(saccade::unstretched(workingStart, workingFinish));
|
|
|
|
|
|
workingStart = theSaccade.start;
|
|
|
|
|
|
workingFinish = theSaccade.finish;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
recollection.push_back(saccade::unstretched(workingStart, workingFinish));
|
|
|
|
|
|
}
|
|
|
|
|
|
return recollection;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void saccades_engine::disconnectEngram(int theSlot) {
|
|
|
|
|
|
saccade_engram& current = engrams.at(theSlot);
|
|
|
|
|
|
saccade_engram& above = engrams.at(current.nextFresh);
|
|
|
|
|
|
above.nextStale = current.nextStale;
|
|
|
|
|
|
|
|
|
|
|
|
if(mostStale == theSlot) {
|
|
|
|
|
|
mostStale = current.nextFresh;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
saccade_engram& below = engrams.at(current.nextStale);
|
|
|
|
|
|
below.nextFresh = current.nextFresh;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
current.nextFresh = saccade_engram::NoneMore;
|
|
|
|
|
|
current.nextStale = saccade_engram::NoneMore;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void saccades_engine::connectFreshestEngram(int theSlot) {
|
|
|
|
|
|
engrams.at(theSlot).nextStale = mostFresh;
|
|
|
|
|
|
if(mostFresh != saccade_engram::NoneMore) {
|
|
|
|
|
|
engrams.at(mostFresh).nextFresh = theSlot;
|
|
|
|
|
|
}
|
|
|
|
|
|
mostFresh = theSlot;
|
|
|
|
|
|
if(mostStale == saccade_engram::NoneMore) {
|
|
|
|
|
|
mostStale = theSlot;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void saccades_engine::freshenEngram(int theSlot) {
|
|
|
|
|
|
if(mostFresh == theSlot) return;
|
|
|
|
|
|
disconnectEngram(theSlot);
|
|
|
|
|
|
connectFreshestEngram(theSlot);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void saccades_engine::makeEngram(saccade s) {
|
|
|
|
|
|
int newSlot = engrams.size();
|
|
|
|
|
|
engrams.push_back(saccade_engram(s));
|
|
|
|
|
|
connectFreshestEngram(newSlot);
|
|
|
|
|
|
markers.insert(saccade_marker(s, newSlot));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void saccades_engine::recycleEngram(saccade s) {
|
|
|
|
|
|
int recycleSlot = mostStale;
|
|
|
|
|
|
saccade_marker dropMarker(engrams.at(recycleSlot).theSaccade, recycleSlot);
|
|
|
|
|
|
markers.erase(dropMarker);
|
|
|
|
|
|
engrams.at(recycleSlot).theSaccade = s;
|
|
|
|
|
|
saccade_marker insertMarker(s, recycleSlot);
|
|
|
|
|
|
markers.insert(insertMarker);
|
|
|
|
|
|
freshenEngram(recycleSlot);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void saccades_engine::evoke(saccade s) {
|
|
|
|
|
|
bool stillGrowing = (capacity > engrams.size());
|
|
|
|
|
|
set<saccade_marker>::iterator i;
|
|
|
|
|
|
saccade_marker testMarker(s,0);
|
|
|
|
|
|
i = markers.find(testMarker);
|
|
|
|
|
|
bool isRemembered = (i != markers.end());
|
|
|
|
|
|
|
|
|
|
|
|
if(isRemembered) {
|
|
|
|
|
|
freshenEngram((*i).theSlot);
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
if(stillGrowing) {
|
|
|
|
|
|
makeEngram(s);
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
recycleEngram(s);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void saccades_engine::learn(vector<saccade>& experiences) {
|
|
|
|
|
|
for(unsigned int i = 0; i < experiences.size(); i++) {
|
|
|
|
|
|
evoke(experiences[i]);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|