Created
June 4, 2020 12:13
-
-
Save PtrMan/1dc7a9ef26425fcbfa0ad215345c6a4e to your computer and use it in GitHub Desktop.
NARS Tutorial codes
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
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