Skip to content

Instantly share code, notes, and snippets.

@PtrMan
Created June 4, 2020 12:13
Show Gist options
  • Save PtrMan/1dc7a9ef26425fcbfa0ad215345c6a4e to your computer and use it in GitHub Desktop.
Save PtrMan/1dc7a9ef26425fcbfa0ad215345c6a4e to your computer and use it in GitHub Desktop.
NARS Tutorial codes
use rand::Rng;
use std::rc::Rc;
use std::cell::RefCell;
// DONE< check for events which were anticipated and remove anticipations! >
// DONE< compute expectation while decision making and take the one with the highest exp(), check against decision threshold! >
// TODO< compute table of exponential intervals! >
// TODO< compute anticipation deadline >
pub fn main() {
let mut rng = rand::thread_rng();
let mut evidence: Vec<Rc<RefCell<EE>>> = Vec::new();
let mut trace: Vec<SimpleSentence> = Vec::new();
let mut ballX:f64 = 3.0;
let mut batX:f64 = 7.0;
let mut batVelX:f64 = 0.0;
let mut anticipatedEvents: Vec<AnticipationEvent> = Vec::new();
for _t in 0..350 {
println!("ae# = {}", anticipatedEvents.len()); // debug number of anticipated events
// remove confirmed anticipations
if trace.len() > 0 {
let curEvent = &trace[trace.len()-1].name;
let mut newanticipatedEvents = Vec::new();
for iDeadline in &anticipatedEvents {
let evi = (*iDeadline).evi.borrow();
if evi.pred != *curEvent { // is predicted event not current event?
newanticipatedEvents.push(iDeadline.clone());
}
}
anticipatedEvents = newanticipatedEvents;
}
{ // neg confirm for anticipated events
{
for iDeadlineViolated in anticipatedEvents.iter().filter(|v| v.deadline <= _t) {
let mut mutEvi = (*iDeadlineViolated).evi.borrow_mut();
mutEvi.eviCnt+=1; // add negative evidence
}
}
// TODO< refactor this as filtering >
{
let mut newanticipatedEvents = Vec::new();
for iDeadline in &anticipatedEvents {
if iDeadline.deadline > _t {
newanticipatedEvents.push(iDeadline.clone());
}
}
anticipatedEvents = newanticipatedEvents;
}
}
if trace.len() >= 3 { // add evidence
// TODO< filter middle by ops and select random first event before that! >
let mut idx0 = rng.gen_range(0, trace.len()-1);
let mut idx1 = rng.gen_range(0, trace.len()-1);
let mut idx2 = trace.len()-1; // last event is always last
let mut idxs = vec![idx0,idx1,idx2];
idxs.sort();
// middle must be op
if trace[idxs[1]].name == "R" || trace[idxs[1]].name == "L" {
// first and last must not be op
if trace[idxs[0]].name != "R" && trace[idxs[0]].name != "L" && trace[idxs[2]].name != "R" && trace[idxs[2]].name != "L" {
// found a potential sequence to be perceived
let e0 = &trace[idxs[0]];
let e1 = &trace[idxs[1]];
let e2 = &trace[idxs[2]];
println!("perceive ({},{})=/>{}", e0.name, e1.name, e2.name);
println!("TODO - improve store (we need to try to revise knowledge)");
let expDt:i64 = e2.occT - e1.occT;
// TODO< compute exponential delta time
evidence.push(Rc::new(RefCell::new(EE {
stamp:vec!(e0.evi,e1.evi,e2.evi),
expDt:expDt,
seqCond:e0.name.clone(),
seqOp:e1.name.clone(),
pred:e2.name.clone(),
eviPos:1,
eviCnt:1,
})));
}
}
}
{
let diff = ballX - batX;
if diff > 1.0 {
trace.push(SimpleSentence {name:"r".to_string(),evi:_t,occT:_t});
}
else if diff < -1.0 {
trace.push(SimpleSentence {name:"l".to_string(),evi:_t,occT:_t});
}
else {
trace.push(SimpleSentence {name:"c".to_string(),evi:_t,occT:_t});
}
}
let cfgDescnThreshold:f64 = 0.48;
let mut pickedAction:Option<String> = None;
match &pickedAction {
Some(act) => {},
None => {
// TODO< search with highest exp and exec only if above descision threshold! >
struct Picked {
evidence:Rc<RefCell<EE>>, // the evidence of the picked option
}
let mut pickedOpt:Option<Picked> = None;
let mut pickedExp:f64 = 0.0;
// search if we can satisfy goal
for iEERc in &evidence {
let iEE:&EE = &(*iEERc).borrow();
// check impl seq first ! for current event!
if iEE.seqCond == trace[trace.len()-1].name && iEE.pred == "c" { // does it fullfil goal?
let iFreq = retFreq(&iEE);
let iConf = retConf(&iEE);
let exp = calcExp(&Tv{f:iFreq,c:iConf});
if exp > pickedExp {
pickedExp = exp;
pickedOpt = Some(Picked{evidence:Rc::clone(iEERc)});
}
}
}
if pickedExp > cfgDescnThreshold {
let picked = pickedOpt.unwrap().evidence;
let implSeqAsStr = format!("({},{})=/>{}",(*picked).borrow().seqCond,(*picked).borrow().seqOp,(*picked).borrow().pred);
println!("descnMaking: found best act = {} implSeq={} exp = {}", (*picked).borrow().seqOp, &implSeqAsStr, pickedExp);
pickedAction = Some((*picked).borrow().seqOp.clone());
// add anticipated event
let deadline:i64 = _t + 5; // TODO< compute read deadline by exponential interval
anticipatedEvents.push(AnticipationEvent {
evi:Rc::clone(&picked),
deadline:deadline,
});
}
},
}
match &pickedAction {
Some(act) => {},
None => {
let p = rng.gen_range(0, 18);
if p == 1 {
pickedAction = Some("L".to_string());
}
else if p == 2 {
pickedAction = Some("R".to_string());
}
}
}
match &pickedAction {
Some(act) => {
if act == "L" {
batVelX = -1.0;
}
else if act == "R" {
batVelX = 1.0;
}
trace.push(SimpleSentence {name:act.clone(),evi:_t,occT:_t});
},
None => {},
}
// limit trace (AIKR)
if trace.len() > 20 {
trace = (&trace[trace.len()-20..]).to_vec();
}
println!("{} {}", trace[trace.len()-1].name, ballX - batX);
batX += batVelX;
// limit bat
if batX < 0.0 {
batX = 0.0;
}
if batX > 10.0 {
batX = 10.0;
}
}
println!("TODO - print all evidence");
}
// evidence
pub struct EE {
pub stamp:Vec<i64>, // collection of evidence of stamp
pub seqCond:String, // condition of sequence
pub seqOp:String, // op of sequence
pub pred:String, // predicate of impl seq
expDt:i64, // exponential time delta
pub eviPos:i64,
pub eviCnt:i64,
}
pub fn retFreq(evidence:&EE)->f64 {
(evidence.eviPos as f64) / (evidence.eviCnt as f64)
}
pub fn retConf(evidence:&EE)->f64 {
(evidence.eviCnt as f64) / ((evidence.eviCnt as f64) + 1.0)
}
// event
// string and evidence
// (emulation of sentence and term)
#[derive(Clone)]
pub struct SimpleSentence {
pub name:String,
pub evi:i64, // evidence id
pub occT:i64, // occurcence time
}
// anticipated event
#[derive(Clone)]
pub struct AnticipationEvent {
pub evi:Rc<RefCell<EE>>, // evidence
pub deadline:i64, // deadline in absolute cycles
}
#[derive(Clone)]
pub struct Tv {
pub f:f64,
pub c:f64,
}
pub fn calcExp(tv:&Tv)->f64 {
tv.c*(tv.f - 0.5)+0.5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment