summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
m---------biscuit7
-rw-r--r--intellect.cpp162
-rw-r--r--makefile2
l---------name.scm1
-rw-r--r--project.scm83
-rw-r--r--random.cpp108
-rw-r--r--starts/bagel/README.md35
-rw-r--r--starts/bagel/nascent1.js107
-rw-r--r--starts/bagel/nascent2.js172
-rw-r--r--starts/bagel/nascent3.js199
-rw-r--r--starts/bagel/nascent4.js242
-rw-r--r--starts/bagel/nascent5.js382
-rw-r--r--starts/bagel/nascent6.js461
-rw-r--r--starts/bagel/notes.txt99
15 files changed, 2063 insertions, 0 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..57ff75b
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "biscuit"]
+ path = biscuit
+ url = https://github.com/xloem/biscuit.git
diff --git a/biscuit b/biscuit
new file mode 160000
+Subproject 2ed6efe8847a4f076c5559122b1dd0a0fb94513
diff --git a/intellect.cpp b/intellect.cpp
new file mode 100644
index 0000000..7991878
--- /dev/null
+++ b/intellect.cpp
@@ -0,0 +1,162 @@
+// The extreme of Trial Exploration and Self Coding
+// brainstorm_by(assembly code,running it)
+
+// the advantage of assembly code is that it is very easy to serialize
+// the advantage of random self-modification is that it is very easy to make
+// propose this is the first AI karl makes, and it runs in a safe isolated box, on its own
+// how to judge success? does-not-crash?
+// have to teach it learning. first is to not crash. then is to output requested string, likely copied from request. run it until it outputs requested string.
+// it's stupid enough to be safe if run in an isolated box.
+// due to how fast it should be to make this, let's finish barebones first, and then merge. XO computer likely doesn't have read-only-execute problem.
+
+// the below is a brief attempt to make an intellect by random self-modification. it does not run.
+// DO NOT RUN THIS UNLESS YOU KNOW WHAT YOU ARE DOING
+
+#include <cstdint>
+#include <vector>
+#include <set>
+#include <iostream>
+
+#include <signal.h>
+//#include <sys/mmap.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+using namespace std;
+
+// Signal Catching has the problem of how to resume execution generally.
+// So we propose to fork a new process, and switch to it if it works.
+// This will take forming a simple communication method between the processes.
+// We can also compile a whole new program to learn, copying our source.
+
+// TODO: Currently implementing fork/exec. changed approach
+
+// TODO: make sure to run inside a vm once it does something
+
+// TODO: try out rewriting and recompiling code, rather than forking ram
+
+class RamGetter
+{
+public:
+ RamGetter()
+ {
+ randfile = open("/dev/urandom", O_RDONLY);
+ if (randfile <= 0) throw 0;
+ }
+ ~RamGetter()
+ {
+ close(randfile);
+ }
+ void * getRandAddr(size_t len)
+ {
+ // TODO: this is a heuristic for picking an inner memory location, and learning what doesn't work; could be used in learning concept
+ void * blkp;
+ do {
+ uint32_t blk;
+ int ct = read(randfile, &blk, sizeof(blk));
+ if (ct < sizeof(blk)) throw 0;
+ blkp = reinterpret_cast<void*>(blk);
+ // fork here. check length
+ pid_t forkpid = fork();
+ if (forkpid == -1) throw "failed to fork";
+ if (forkpid == 0) {
+ // child: test ram
+ volatile uint8_t tst;
+ for (size_t i = 0; i < len; ++ i) {
+ tst = ((uint8_t*)blkp)[i];
+ }
+ } else {
+ // parent: wait for child
+ int status;
+ wait(&status);
+ if(WIFCONTINUED(status)) {
+ // child succeeded, so we can stop
+ // TODO: need a way to indicate child success
+ exit(0);
+ } else {
+ // child failed, so we keep going, but TODO: failure is not stored
+ continue;
+ }
+ }
+ } while (isbad(blkp));
+ return blkp;
+ }
+ void markbad(void *bad)
+ {
+ bad = (void*)((long)(bad) & ~0xfff);
+ badpages.insert(bad);
+ cout << "Bad: " << bad << endl;
+ }
+ bool isbad(void *chk)
+ {
+ chk = (void*)((long)(chk) & ~0xfff);
+ return badpages.count(chk);
+ }
+
+private:
+ int randfile;
+ set<void*> badpages;
+ // TODO: some concern that the badpages set will allocate on the heap.
+ // maybe let's use a stack-based storage back for it (allocator)
+};
+
+
+uint8_t someram[0x10000000]; // when this is removed, heap moves to 64-bit?
+struct instruction {
+ void * verb;
+ void * object1;
+ void * object2;
+ void * attr;
+ void * result;
+};
+
+int main() {
+ // reference process memory
+ // all of it, please
+ RamGetter selfmem; // an object to access RAM with
+
+ // TODO: try making an instruction list
+
+ void * mem = 0;
+ // make a loop
+ while (true) {
+ // TODO: move fork/exec into this loop, outside of RamGetter
+
+ // we propose copying some blocks to other blocks, randomly
+ // need blocksize, how about 4 // TODO: that's kinda small, maybe random instead?
+ void *blk1, *blk2;
+ blk1 = selfmem.getRandAddr(4);
+ blk2 = selfmem.getRandAddr(4);
+ memmove(blk1, blk2, 4);
+
+ // continue the loop forever
+ // run it
+ }
+ // end when the loop is done =)
+
+ // /proc/pid/maps shows the addresses of allocated memory
+ // /proc/pid/mem provides access to this memory
+ // ^-- will error when wrong part is read
+ // just load straight; error is recoverable, just a refusal
+ // no need to map file, can just catch segfaults?
+
+ /*
+ FILE *maps;
+ char pathbuf[1024];
+ snprintf("/proc/%d/maps", sizeof(pathbuf), pid);
+ open(pathbuf, O_RDONLY);
+
+ snprintf("/proc/%d/mem", sizeof(pathbuf), pid);
+ void * procmem = mmap(0, length, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED
+ */
+ /*
+ try {
+ int e = *(int*)39;
+ } catch(...) {
+ throw;
+ }
+ */
+}
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..9475287
--- /dev/null
+++ b/makefile
@@ -0,0 +1,2 @@
+intellect: intellect.cpp
+ g++ -ggdb -std=c++11 intellect.cpp -Wl,--print-map
diff --git a/name.scm b/name.scm
new file mode 120000
index 0000000..b8d26ee
--- /dev/null
+++ b/name.scm
@@ -0,0 +1 @@
+../time_reversal/name.scm \ No newline at end of file
diff --git a/project.scm b/project.scm
new file mode 100644
index 0000000..3e7d69f
--- /dev/null
+++ b/project.scm
@@ -0,0 +1,83 @@
+; This is our intellect project.
+
+; These lines initialise OpenCog, a dependency.
+; TODO: make makefile to install opencog if needed, and run
+(use-modules (ice-9 readline)) (activate-readline)
+(add-to-load-path "/usr/local/share/opencog/scm")
+(add-to-load-path ".")
+(use-modules (opencog))
+(use-modules (opencog query))
+(use-modules (opencog exec))
+
+; Please change this as you best judge.
+; Please talk with us.
+; Please try this out, safely, as you best judge, and let us know how it goes.
+
+; cog-execute:
+; atoms can have dual meaning, knowledge and behavior
+; if a process results in an atom, it is remembered in the current context
+; context is an AtomSpace
+
+; concept: application to whole process
+; concept: generalization of habit
+; concept: presenting habit as proposal
+
+(holy fuck)
+(pretty sure you can type like this karl)
+(pretty sure you will eventually figure that out)
+
+; too bad ben didn't
+; let's put human-langugae comments prior to patterns
+
+; one of the issues was fear-of-private AI. so intro words help.
+; one issue is "this is too much like a brain. are we mind-control?" i think it's trying to prevent copies.
+
+; ignoring below for now ... hearing it doesn't matter, but probably lots of work went in
+; good thought
+
+; concept made from simple parts that nurture themselves
+
+; define a part: (define name (ConceptNode "Name"))
+
+; PROBLEM: need a way to make custom link
+; PROBLEM: plans not found, making anew
+
+
+; component: urgency to continue & reference across time
+; component: pattern recognition
+; component: brainstorming to produce matching
+; component: generalization
+; component: write steps in terms of each other with meaning
+; component: process as data
+
+; component: competition,collaboration,or cooperation of parts, to identify collaborative method
+
+(define habit-urgency (ConceptNode "HabitUrgency"))
+ ; habit urgency
+ ; step-by-step behavior. do the next step after this one
+ ; ^-- to define need to define in terms of self: habit-urgency-steps for habit-urgency are to do-the-next-step.
+ ; ^-- can also define in terms of time-relative-to-now. given list of steps, action is one after present one
+
+(define pattern-match (ConceptNode "PatternMatch"))
+ ; pattern matching
+ ; component: identify that a set of data matches a pattern
+ ; component: identify that a pattern matches a set of data
+ ; component: _find_ data to match pattern
+ ; component: _find_ pattern to match data
+
+
+(define brainstorm (ConceptNode "Brainstorm"))
+ ; finds a new set of data that matches a pattern
+
+(define generalization (ConceptNode "Generalization"))
+ ; finds a new pattern that matches a set of data
+
+(define test-patternmatch-brainstorm (ConceptNode "TestPatternMatchBrainstorm"))
+ ; BRAINSTORM data that matches a pattern from IMAGINARY, RANDOM set
+ ; TEST that PATTERNMATCH identifies the data and pattern as matching
+
+
+; write steps in terms of each other with meaning
+; our data is our process & code
+
+
diff --git a/random.cpp b/random.cpp
new file mode 100644
index 0000000..afdf4c7
--- /dev/null
+++ b/random.cpp
@@ -0,0 +1,108 @@
+// let's try to make it very simple
+
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+// 1. write a function to randomly put data in a buffer
+// [apparently one loaded from a file]
+
+#define MAPFNAME "random.bin"
+
+pid_t child = 0;
+bool child_terminated = false;
+void handleSigChld(int)
+{
+ child_terminated = true;
+}
+
+static unsigned long long * count;
+
+void random(int mapfd, int randfd, void *addr)
+{
+ pid_t pid = getpid();
+
+ // *count is shared and stored
+ for (*count = 0; ; ++ *count) {
+ unsigned long long old_count = *count;
+
+ // if successful child, update & kill parent
+ if (getpid() != pid) {
+ msync(addr + pos, size, MS_SYNC | MS_INVALIDATE);
+
+ kill(pid, SIGTERM);
+ pid = getpid();
+
+ // add data to git.
+ system("git add " MAPFNAME);
+ system("git commit -m selfmod");
+ }
+
+ // handle crashes with fork()
+ child = fork();
+ if (child == 0) {
+ // we are new child process
+ // self-modify by 1-8 bytes
+ uint16_t pos;
+ uint8_t size;
+ read(randfd, &pos, sizeof(pos));
+ read(randfd, &size, sizeof(size));
+ size = (size & 0x7) + 1; // self-modify by 1-8 bytes
+ read(randfd, addr + pos, size);
+ // loop
+ } else {
+ // old process: make sure new process succeeds within 1s
+ time_t then = time(0);
+ for (;;) {
+ if (child_terminated || time(0) > then) {
+ // child did not succeed
+ kill(child, SIGTERM);
+ child_terminated = false;
+ // try again
+ break;
+ }
+ if (old_count < *count + 1) {
+ // incremented count by 1: success; hand off to child
+ return;
+ }
+ }
+ }
+ }
+}
+
+void random_tail() {
+}
+
+void main()
+{
+ // handle SIGCHLD by setting a global flag
+ struct sigaction sigchld;
+ sigchld.sa_handler = handleSigChld;
+ sigchld.sa_flags = SA_NOCLDWAIT;
+ sigaction(SIGCHLD, &sigchld, NULL);
+
+ int fd = open(MAPFNAME, O_RDWR);
+ if (fd == -1 && errno == ENOENT) {
+ // does not exist yet
+ fd = open("random.bin", O_RDWR | O_CREAT);
+ // 2. seed the buffer with the function that puts random data in it
+ count = 0;
+ write(fd, &count, sizeof(count));
+ write(fd, &random, &random_tail - &random);
+ }
+
+ int randfd = open("/dev/random", O_RDONLY);
+
+ // a buffer of 1 gig working space; random data will fill it
+ void *buf = mmap(NULL,
+ 0x40000000,
+ PROT_EXEC | PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_32BIT,
+ fd,
+ 0;
+
+ // 3. execute the buffer
+ void (*buf_as_func)(void*) = (void*)((uint8_t*)buf + count);
+ buf_as_func(mapfname, mapfd, randfd, buf);
+}
diff --git a/starts/bagel/README.md b/starts/bagel/README.md
new file mode 100644
index 0000000..9996ce9
--- /dev/null
+++ b/starts/bagel/README.md
@@ -0,0 +1,35 @@
+# bagel
+well really it's a little hobby sentient-AI idea, but it's too small to do or be anything
+
+# relevence
+The idea is kind of that our minds have a very fancy network of nearness and farness of concepts.
+When I think about something -- brainstorm on it -- my mind activates it and it activates relevent associated thoughts.
+It pours through different thoughts that are nearby by association, and keeps the ones that are more useful, more relevent, while
+discarding the ones that aren't.
+
+# self-reference
+Additionally, my mind when working on a task, can improve the actual process of working on the task. The steps can change.
+The process for finding steps can change. The whole goal can change. I can even go out and wonder why I am working the task
+in the first place, and think about that. Then I can act on the new decision.
+By making code that writes itself, we move towards an intellect that can learn and improve.
+
+# implementation ideas
+I wrote out some quick relevence around how I might write code, and it seemed like the 'why' for each step was basically a small
+chunk of code itself. It seems like there are relevent concepts in my mind that are roughly linked to these small behaviors
+(habits or chunks of code). By making such links in actual code, the code looks more mindlike to me.
+One of the keys is to get the code to make the links itself, and I think what is important there is the concept of patterns-that-
+work. If you can discern when code works, then you can look for similar properties on the before and end states. If some of them
+are always the same when it works, those are probably the ones that should be linked to the code chunk under study. This provides
+for rudimentary learning.
+
+# size
+This code is written very tiny so that little work need be invested in it for it have conceptual growth. The idea and hope somehow
+is that it move rapidly towards coding itself, such that as it gets coded, the developer need do less to work on it, being able to
+instead make use of its internal functions for producing code-like behavior.
+
+# language
+By prototyping in a flexible language like Javascript, design work may be hastened a little. I also theorize that a good AI doesn't
+need many cpu cycles to get stuff done, because it makes smart choices.
+
+# etc
+There is of course more. This writing content was made day-of-creation. Will I ever edit this again? Unknown.
diff --git a/starts/bagel/nascent1.js b/starts/bagel/nascent1.js
new file mode 100644
index 0000000..b6b5552
--- /dev/null
+++ b/starts/bagel/nascent1.js
@@ -0,0 +1,107 @@
+class ActiveMemory {
+ constructor() {
+ this.ram = []
+ this.cloned = false
+ }
+ clone() {
+ let ret = new ActiveMemory();
+ ret.ram = this.ram
+ ret.cloned = true
+ return ret
+ }
+ add(item) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ this.ram.push(item)
+ }
+ del(item) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ let index = this.ram.indexOf(item)
+ this.ram.splice(index, 1)
+ }
+ contains(item) {
+ for (let a of this.ram)
+ if (a == item) return a
+ return false
+ }
+ containsWith(prop, val) {
+ let ret = []
+ for (let a of this.ram)
+ if (a[prop] == val)
+ return true
+ return false
+ }
+ getWith(prop, val) {
+ let ret = []
+ //console.log('get-with ' + prop + ' ' + val)
+ for (let a of this.ram) {
+ //console.log(a + ' ' + prop + ' is ' + a[prop])
+ if (a[prop] == val)
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+
+function sayhi() {
+ res = 'hi'
+ res.use = 'output'
+ console.log(res)
+ return 'said ' + res
+}
+sayhi.relevence = function(ram) {
+ return [ram.ram[0]];
+}
+
+function line2words(line) {
+ let res = line.split(' ')
+ res.type = 'list'
+ return res
+}
+line2words.relevence = function(ram) {
+ return ram.getWith('type', 'text')
+}
+
+all_parts = [ line2words, sayhi ]
+
+ram = new ActiveMemory()
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new String(line)
+ line.use = 'input'
+ line.type = 'text'
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ let rel = part.relevence(ram)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part(a)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ optstried.add(part.name + ' ' + a)
+
+ }
+ }
+ //if (rel) {
+ // let ram2 = ram.clone()
+ // for
+ //}
+ }
+ } while (cont)
+})
diff --git a/starts/bagel/nascent2.js b/starts/bagel/nascent2.js
new file mode 100644
index 0000000..883aa7a
--- /dev/null
+++ b/starts/bagel/nascent2.js
@@ -0,0 +1,172 @@
+class ActiveMemory {
+ constructor() {
+ this.ram = []
+ this.cloned = false
+ }
+ clone() {
+ let ret = new ActiveMemory();
+ ret.ram = this.ram
+ ret.cloned = true
+ return ret
+ }
+ add(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items)
+ this.ram.push(item)
+ }
+ del(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items) {
+ let index = this.ram.indexOf(item)
+ this.ram.splice(index, 1)
+ }
+ }
+ contains(...items) {
+ for (let item of items)
+ if (this.ram.indexOf(item) === -1) return false
+ return true
+ }
+ containsWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ for (let b of props)
+ if (! a.has(b))
+ continue outer
+ return true
+ }
+ return false
+ }
+ getWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ for (let b of props)
+ if (! a.has(b))
+ continue outer
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+class StringData extends String {
+ constructor(str, from) {
+ super(str)
+ this.props = new Set(from && from.props)
+ this.add('string')
+ this.del('array')
+ }
+ add(val) {
+ this.props.add(val)
+ }
+ has(val) {
+ return this.props.has(val)
+ }
+ del(val) {
+ this.props.delete(val)
+ }
+}
+class ArrayData extends Array {
+ constructor(arr, from) {
+ super(...arr)
+ this.props = new Set(from && from.props)
+ this.add('array')
+ this.del('string')
+ }
+ add(val) {
+ this.props.add(val)
+ }
+ has(val) {
+ return this.props.has(val)
+ }
+ del(val) {
+ this.props.delete(val)
+ }
+}
+
+function line2words(line) {
+ let res = new ArrayData(line.split(' '), line)
+ res.add('words')
+ return res
+}
+line2words.relevence = function(ram) {
+ return ram.getWith('text', 'string')
+}
+line2words.makes = ['array','words'] // property values produced
+
+function respondhello(words) {
+ console.log(words[0] + ", user!")
+ let res = new StringData("said " + words[0])
+ res.add('output')
+ res.add('text')
+ return res
+}
+respondhello.relevence = function(ram) {
+ let res = ram.getWith('words', 'input')
+ if (res) res = res.filter(x => { x = x[0].toLowerCase(); return x == 'hello' || x == 'hi'})
+ return res
+}
+respondhello.makes = ['output']
+
+// nodejs is missing a succinct read-line-from-stdin function. here, we make one.
+userinput = (() => {
+ const readline = require('readline')
+ const lines = []
+ readline.createInterface({ input: process.stdin }).on('line', (line) => {
+ lines.push(line)
+ })
+
+ function userinput() {
+ let res = new StringData(lines.shift())
+ res.add('text')
+ res.add('input')
+ return res
+ }
+ userinput.relevence = function() {
+ return lines.length > 0
+ }
+ userinput.makes = ['string','text','input']
+
+ return userinput
+})()
+
+
+all_parts = [ line2words, respondhello ]
+
+ram = new ActiveMemory()
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new StringData(line)
+ line.add('input')
+ line.add('text')
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ let rel = part.relevence(ram)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part(a)
+ ram.add(res)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ optstried.add(part.name + ' ' + a)
+
+ }
+ }
+ }
+ } while (cont)
+})
diff --git a/starts/bagel/nascent3.js b/starts/bagel/nascent3.js
new file mode 100644
index 0000000..0a6c4a3
--- /dev/null
+++ b/starts/bagel/nascent3.js
@@ -0,0 +1,199 @@
+class ActiveMemory {
+ constructor() {
+ this.ram = []
+ this.cloned = false
+ }
+ clone() {
+ let ret = new ActiveMemory();
+ ret.ram = this.ram
+ ret.cloned = true
+ return ret
+ }
+ add(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items)
+ this.ram.push(item)
+ }
+ del(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items) {
+ let index = this.ram.indexOf(item)
+ this.ram.splice(index, 1)
+ }
+ }
+ contains(...items) {
+ for (let item of items)
+ if (this.ram.indexOf(item) === -1) return false
+ return true
+ }
+ containsWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ for (let b of props)
+ if (! a.has(b))
+ continue outer
+ return true
+ }
+ return false
+ }
+ getWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ for (let b of props)
+ if (! a.has(b))
+ continue outer
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+class StringData extends String {
+ constructor(str, from) {
+ super(str)
+ this.props = new Set(from && from.props)
+ this.add('string')
+ this.del('array')
+ }
+ add(val) {
+ this.props.add(val)
+ }
+ has(val) {
+ return this.props.has(val)
+ }
+ del(val) {
+ this.props.delete(val)
+ }
+}
+class ArrayData extends Array {
+ constructor(arr, from) {
+ super(...arr)
+ this.props = new Set(from && from.props)
+ this.add('array')
+ this.del('string')
+ }
+ add(val) {
+ this.props.add(val)
+ }
+ has(val) {
+ return this.props.has(val)
+ }
+ del(val) {
+ this.props.delete(val)
+ }
+}
+class FunctionData {
+ constructor(name, func, relevence, makes) {
+ this.name = name
+ this.props = new Set()
+ this.props.add('function')
+ this.props.add(name)
+ this.call = func
+ this.relevence = relevence
+ this.makes = makes
+ }
+ add(val) {
+ this.props.add(val)
+ }
+ has(val) {
+ return this.props.has(val)
+ }
+ del(val) {
+ this.props.delete(val)
+ }
+}
+
+line2words = new FunctionData(
+ 'line2words',
+ (line) => { // call
+ let res = new ArrayData(line.split(' '), line)
+ res.add('words')
+ return res
+ },
+ (ram) => { // relevence
+ return ram.getWith('text', 'string')
+ },
+ ['array','words'] // makes
+)
+
+respondhello = new FunctionData(
+ 'respondhello',
+ (words) => { // call
+ console.log(words[0] + ", user!")
+ let res = new StringData("said " + words[0])
+ res.add('output')
+ res.add('text')
+ return res
+ },
+ (ram) => { // relevence
+ let res = ram.getWith('words', 'input')
+ if (res) res = res.filter(x => { x = x[0].toLowerCase(); return x == 'hello' || x == 'hi'})
+ return res
+ },
+ ['output', 'text'] // makes
+)
+
+// nodejs is missing a succinct read-line-from-stdin function. make our own.
+userinput = (() => {
+ const readline = require('readline')
+ const lines = []
+ readline.createInterface({ input: process.stdin }).on('line', (line) => {
+ lines.push(line)
+ })
+
+ return new FunctionData(
+ 'userinput',
+ () => { // call
+ let res = new StringData(lines.shift())
+ res.add('text')
+ res.add('input')
+ return res
+ },
+ () => { // relevence
+ return lines.length > 0
+ },
+ ['string','text','input'] // makes
+ )
+})()
+
+
+all_parts = [ line2words, respondhello ]
+
+ram = new ActiveMemory()
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new StringData(line)
+ line.add('input')
+ line.add('text')
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ let rel = part.relevence(ram)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part.call(a)
+ ram.add(res)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ optstried.add(part.name + ' ' + a)
+
+ }
+ }
+ }
+ } while (cont)
+})
diff --git a/starts/bagel/nascent4.js b/starts/bagel/nascent4.js
new file mode 100644
index 0000000..093df79
--- /dev/null
+++ b/starts/bagel/nascent4.js
@@ -0,0 +1,242 @@
+class ActiveMemory {
+ constructor() {
+ this.ram = []
+ this.cloned = false
+ }
+ clone() {
+ let ret = new ActiveMemory();
+ ret.ram = this.ram
+ ret.cloned = true
+ return ret
+ }
+ add(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items)
+ this.ram.push(item)
+ }
+ del(...items) {
+ if (this.cloned) { this.ram = this.ram.slice(); this.cloned = false; }
+ for (let item of items) {
+ let index = this.ram.indexOf(item)
+ this.ram.splice(index, 1)
+ }
+ }
+ contains(...items) {
+ for (let item of items)
+ if (this.ram.indexOf(item) === -1) return false
+ return true
+ }
+ containsWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ for (let i = 0; i < props.length; i += 2)
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ return true
+ }
+ return false
+ }
+ getWith(...props) {
+ let ret = []
+ outer: for (let a of this.ram) {
+ //console.log(a.props.props)
+ for (let i = 0; i < props.length; i += 2) {
+ //console.log(props[i] + ': ' + props[i+1] + '?')
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ }
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+class Property {
+ constructor(type, dest) {
+ this.type = type
+ this.dest = dest
+ }
+}
+class Properties {
+ constructor(type, from) {
+ this.props = from ? from.props.slice() : []
+ //if (from) {console.log('INHERIT: '); for (let prop of this.props) { console.log(prop) }}
+ this.add('is', type)
+ }
+ toString() {
+ let str = ''
+ for (let prop of this.props) {
+ str += prop.type + ':' + prop.dest + ' '
+ }
+ return str
+ }
+ add(type, dest) {
+ this.props.push(new Property(type, dest))
+ }
+ has(type, dest) {
+ for (let p of this.props)
+ if (p.type == type && p.dest == dest)
+ return true
+ return false
+ }
+ del(type, dest) {
+ for (let i = 0; i < this.props.length; ++ i) {
+ let p = this.props[i]
+ if (p.type == type && p.dest == dest) {
+ this.props.splice(i, 1)
+ return true
+ }
+ }
+ return false
+ }
+}
+class AbstractData {
+ constructor(from) {
+ this.props = new Properties('abstract', from && from.props)
+ }
+}
+class StringData extends String {
+ constructor(str, from) {
+ super(str)
+ this.props = new Properties('string', from && from.props)
+ this.props.del('is', 'array')
+ }
+}
+class ArrayData extends Array {
+ constructor(arr, from) {
+ super(...arr)
+ this.props = new Properties('array', from && from.props)
+ this.props.del('is', 'string')
+ }
+}
+class FunctionData {
+ constructor(name, func, relevence, makes) {
+ this.name = name
+ this.props = new Properties('function')
+ this.props.add('name', name)
+ this.call = func
+ this.relevence = relevence
+ this.makes = makes
+ }
+}
+
+// variables:
+// - create a place to store a value
+// createvar = new FunctionData(
+// 'createvar',
+// /*call*/(name) => {
+// let ret = new StringData(name)
+// ret.add
+// let name = obj_and_name[1]
+// },
+// /*relevence*/,
+// /*makes*/
+// )
+// - place a value in such a place
+// - retrieve a value from such a place
+// data-structures:
+// - make a class definition (collection of variables)
+// - initialize an object
+// - set/retrieve properties (variables)
+// flow:
+// - trigger a different step than the next, conditionally
+// procedures:
+// - collect a set of behaviors together
+// - trigger a collected set of behaviors and continue
+// expressions:
+// - evaluate arithmetic on variables and constants
+
+line2words = new FunctionData(
+ 'line2words',
+ (line) => { // call
+ let res = new ArrayData(line.split(' '), line)
+ res.props.add('is','words')
+ return res
+ },
+ (ram) => { // relevence
+ return ram.getWith('is','text', 'is','string')
+ },
+ ['is','array','is','words'] // makes
+)
+
+respondhello = new FunctionData(
+ 'respondhello',
+ (words) => { // call
+ console.log(words[0] + ", user!")
+ let res = new StringData("said " + words[0])
+ res.props.add('is','output')
+ res.props.add('is','text')
+ return res
+ },
+ (ram) => { // relevence
+ let res = ram.getWith('is','words', 'is','input')
+ if (res) res = res.filter(x => { x = x[0].toLowerCase(); return x == 'hello' || x == 'hi'})
+ return res
+ },
+ ['is','output', 'is','text'] // makes
+)
+
+// nodejs is missing a succinct read-line-from-stdin function. make our own.
+userinput = (() => {
+ const readline = require('readline')
+ const lines = []
+ readline.createInterface({ input: process.stdin }).on('line', (line) => {
+ lines.push(line)
+ })
+
+ return new FunctionData(
+ 'userinput',
+ () => { // call
+ let res = new StringData(lines.shift())
+ res.props.add('is','text')
+ res.props.add('is','input')
+ return res
+ },
+ () => { // relevence
+ return lines.length > 0
+ },
+ ['is','string','is','text','is','input'] // makes
+ )
+})()
+
+
+all_parts = [ line2words, respondhello ]
+
+ram = new ActiveMemory()
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new StringData(line)
+ line.props.add('is','input')
+ line.props.add('is','text')
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ let rel = part.relevence(ram)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part.call(a)
+ ram.add(res)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ optstried.add(part.name + ' ' + a)
+
+ }
+ }
+ }
+ } while (cont)
+})
diff --git a/starts/bagel/nascent5.js b/starts/bagel/nascent5.js
new file mode 100644
index 0000000..1d9e8ae
--- /dev/null
+++ b/starts/bagel/nascent5.js
@@ -0,0 +1,382 @@
+class Property {
+ constructor(type, dest) {
+ this.type = type
+ this.dest = dest
+ }
+}
+class Properties {
+ constructor(type, from) {
+ this.props = from ? from.props.slice() : []
+ //if (from) {console.log('INHERIT: '); for (let prop of this.props) { console.log(prop) }}
+ this.add('is', type)
+ }
+ toString() {
+ let str = ''
+ for (let prop of this.props) {
+ str += prop.type + ':' + prop.dest + ' '
+ }
+ return str
+ }
+ add(type, dest) {
+ this.props.push(new Property(type, dest))
+ }
+ has(type, dest) {
+ for (let p of this.props)
+ if ((p.type == type || isVar(type))
+ && (p.dest == dest || isVar(dest)))
+ return true
+ return false
+ }
+ del(type, dest) {
+ for (let i = 0; i < this.props.length; ++ i) {
+ let p = this.props[i]
+ if (p.type == type && p.dest == dest) {
+ this.props.splice(i, 1)
+ return true
+ }
+ }
+ return false
+ }
+ hasIsVar() {
+ return this.has('is','variable')
+ }
+}
+class AbstractData {
+ constructor(from) {
+ this.props = new Properties('abstract', from && from.props)
+ }
+}
+class StringData extends String {
+ constructor(str, from) {
+ super(str)
+ this.props = new Properties('string', from && from.props)
+ this.props.del('is', 'array')
+ }
+}
+class ArrayData extends Array {
+ constructor(arr, from) {
+ super(...arr)
+ this.props = new Properties('array', from && from.props)
+ this.props.del('is', 'string')
+ }
+}
+
+// Abstractions?
+const VAR_X = new StringData('X')
+VAR_X.props.add('is','variable')
+// recommend e.g. 'is','variable-rep' when code is designing them, so don't match everything
+function isVar(x) {
+ return x.props && x.props.has('is','variable')
+}
+
+// MEMORY
+// the archivist. Provides for needs of data. Memory is relevent whenever there is
+// an informational need.
+//
+// When remembering steps, likely what is relevent is what is needed to reach the goal
+// Here's a possible step memory.
+//
+// let ret = new StringData('labeled ' + items.length + ' text-string')
+// ret.props.add('is','step-memory')
+// ret.props.add('step',genproptextstring)
+// ret.props.add('ram',ram)
+// ret.props.add('count',items.length)
+// for (let a of items)
+// ret.props.add('item', a)
+
+class ActiveMemory extends ArrayData {
+ // although Memory is eventually a module that provides for stored information needs
+ // this class is just a group of concepts, moved in and out as needed
+ constructor(items, from) {
+ super(items || [], from)
+ this.props.add('is','working-ram')
+ }
+ clone() {
+ return new ActiveMemory(this, this);
+ }
+ add(...items) {
+ //if (this.cloned) { this = this.slice(); this.cloned = false; }
+ for (let item of items)
+ this.push(item)
+ }
+ del(...items) {
+ //if (this.cloned) { this = this.slice(); this.cloned = false; }
+ for (let item of items) {
+ let index = this.indexOf(item)
+ this.splice(index, 1)
+ }
+ }
+ contains(...items) {
+ for (let item of items)
+ if (this.indexOf(item) === -1) return false
+ return true
+ }
+ containsWith(...props) {
+ let ret = []
+ outer: for (let a of this) {
+ for (let i = 0; i < props.length; i += 2)
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ return true
+ }
+ return false
+ }
+ getWith(...props) {
+ let ret = []
+ outer: for (let a of this) {
+ //console.log(a.props.props)
+ for (let i = 0; i < props.length; i += 2) {
+ //console.log(props[i] + ': ' + props[i+1] + '?')
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ }
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+// note: for now we produce only data; state-changes are data-changes
+class FunctionData {
+ constructor(name, // name of function
+ func, // function taking ordered needs
+ // ordered array of made objects is returned
+ needs, // array of 1-property-per-object this function requires
+ makes // array of 1-property-per-object this function produces
+ ) {
+ this.name = name
+ this.props = new Properties('function')
+ this.props.add('name', name)
+ this.call = func
+ // If needed, make atomspace-like pattern structures for needs/makes.
+ // - represent multiple properties on 1 needed object
+ // - represent input objects present in output
+ this.needs = needs
+ this.makes = makes
+ }
+}
+
+// variables:
+// - create a place to store a value
+//createvar = new FunctionData(
+// 'createvar',
+// /*call*/(name) => {
+// let ret = new StringData(name)
+// ret.props.add('is','varspec')
+// return ret
+// },
+// /*relevence*/,
+//// when do you want to create a variable? when you need a variable and you have a name
+// /*makes*/
+//)
+// - place a value in such a place
+// - retrieve a value from such a place
+// data-structures: (these are like promises of what to do and how to use something)
+// - make a class definition (collection of variables)
+// - initialize an object
+// - set/retrieve properties (variables)
+// flow:
+// - trigger a different step than the next, conditionally
+// procedures:
+// - collect a set of behaviors together
+// - trigger a collected set of behaviors and continue
+// expressions:
+// - evaluate arithmetic on variables and constants
+
+line2words = new FunctionData(
+ 'line2words',
+ (line) => { // call
+ let res = new ArrayData(line.split(' '), line)
+ res.props.add('is','words')
+ res.props.del('is','text-string')
+ return res
+ },
+ ['is','text-string'], // needs
+ ['is','word-array'] // makes
+)
+
+// makes text-string used by line2words. example of small relevence habit
+genproptextstring = new FunctionData(
+ 'genproptextstring',
+ /*call*/(text) => {
+ if (text.props.has('is','string')) {
+ if (!text.props.has('is','text-string')) {
+ text.props.add('is','text-string')
+ }
+ return text
+ }
+ return null
+ },
+ /*needs*/['is','text'],
+ /*makes*/['is','text-string']
+)
+
+respondhello = new FunctionData(
+ 'respondhello',
+ (words) => { // call
+ console.log(words[0] + " world!")
+ let res = new StringData("said " + words[0])
+ res.props.add('is','output')
+ res.props.add('is','text')
+ return res
+ },
+ ['is','hello-input'], // needs
+ ['is','output'] // makes
+)
+
+genprophelloinput = new FunctionData(
+ 'genprophelloinput',
+ /*call*/(input) => {
+ if (!input.props.has('is','words'))
+ return null
+ if (!input.props.has('is','hello-input')) {
+ let x = input[0].toLowerCase()
+ let c = x[x.length-1]
+ if (c == ',' || c == '!' || c == '.') x = x.slice(0,x.length-1)
+ if (x != 'hello' && x != 'hi') return null
+ input.props.add('is','hello-input')
+ }
+ return input
+ },
+ /*needs*/['is','input'],
+ /*makes*/['is','hello-input']
+)
+
+/* old, this isn't relevent to needed structure
+// nodejs is missing a succinct read-line-from-stdin function. make our own.
+userinput = (() => {
+ const readline = require('readline')
+ const lines = []
+ readline.createInterface({ input: process.stdin }).on('line', (line) => {
+ lines.push(line)
+ })
+
+ let ret = new FunctionData(
+ 'userinput',
+ (self) => { // call
+ let res = new StringData(lines.shift())
+ res.props.add('is','text')
+ res.props.add('is','input')
+ return res
+ },
+ () => { // relevence
+ return lines.length > 0
+ },
+ ['has','userinput-lines'] // needs
+ ['is','string','is','text','is','input'] // makes
+ )
+ ret.lines = lines
+})()
+genprophaslines = new FunctionData(
+ 'genprophaslines',
+ (userinput) => { // call
+ }
+)
+*/
+
+// PATTERN REQUEST: we want to be able to store needed-steps.
+// needed-steps are parallel needs that are needed for a helpful step
+// any one may be met, and others are ignored once one is, but all are generated at once
+// habits that meet needs expect them not to be inside an array and have no way of referring to that.
+// [AND needs can be collapsed, but OR needs need patterns]
+// [how do we pull a need out of the list?]
+
+// make a habit that plans core behavior
+// for some other ideas, see this function in nascent6.js
+findstepsfor = new FunctionData(
+ 'findstepsfor',
+ /*call*/(need, depth) => {
+ // find a habit that does the final goal.
+ // TODO: for now we assume all needs are 'is' and store just what-it-is in the need string. when doesn't work anymore, make type-getters on Properties to retrieve the need details
+ let ret = new ArrayData([])
+ for (let habit of all_parts) {
+ if (habit.makes.indexOf(need) !== -1) {
+ // found a workable habit
+ ret.push(habit.needs)
+ }
+ }
+ ret.props.add('is','alternate-needs-array')
+ return ret
+ },
+ // TODO: likely need more structure here
+ /*needs*/['is','desired-need'],
+ /*makes*/['is','alternate-needs-array']
+)
+
+// TODO: add structure enough to build findstepsfor
+// TODO: build findstepsfor
+// TODO 2: add to surrounding process: remove source needs when there is no longer a reason for their presence
+
+
+all_parts = [ line2words, genproptextstring, respondhello, genprophelloinput ]
+
+ram = new ActiveMemory()
+//ram.add(ram)
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new StringData(line)
+ line.props.add('is','input')
+ line.props.add('is','text')
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ // TODO: >1 parameter,must redo next line
+ let rel = ram.getWith(...part.needs)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part.call(a)
+ optstried.add(part.name + ' ' + a)
+ if (res == null) continue
+ // TODO: res==null is considered failure now
+ ram.add(res)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ }
+ }
+ }
+ } while (cont)
+})
+
+
+// it looks like there is a reason to store each item in active memory.
+// one reason is that it is needed by a step in a process.
+// when there are no reasons, it is removed.
+// using an item should link it to what it is used by, so that it may be found easier again when needed
+
+// Please grow to understand your own structure. What is needed to make an intellect?
+// ^-- we want it to learn the basic needs of life, eventually, on its own.
+// notably those to do with care for others.
+
+// MEMORY: see MEMORY above
+
+// RELEVENCE: the gofer. Provides the link between needs, etc, and the behavior that
+// finds them. Is relevent for meeting needs in active ways and likely much else.
+
+// BEHAVIOR: the core. combines interdependent habits from memory to meet needs.
+// The two below go on simultaneously. only 1 is needed.
+// A way to plan behavior:
+// find habits that do the final goal, discern their needs
+// pick needs to treat as a new final goal and repeat until needs are met
+// A way to make behavior:
+// find a habit that does a goal
+// find with this process, information that meets its needs <spawns more>
+// run it
+// TODO: for subprocesses spawning,
+// consider labelling things that are very quick and side-effect-free
+// these can probably be immediately run.
+//
diff --git a/starts/bagel/nascent6.js b/starts/bagel/nascent6.js
new file mode 100644
index 0000000..d7241ba
--- /dev/null
+++ b/starts/bagel/nascent6.js
@@ -0,0 +1,461 @@
+// This file was WIP, two prongs were being pursued at once when work was halted.
+
+// Meaning Representation
+class Property {
+ constructor(type, dest) {
+ this.type = type
+ this.dest = dest
+ }
+}
+class Properties {
+ // members are all Usage Simplification defining Promise Spec
+ constructor(type, from) {
+ this.props = from ? from.props.slice() : []
+ //if (from) {console.log('INHERIT: '); for (let prop of this.props) { console.log(prop) }}
+ this.add('is', type)
+ }
+ toString() {
+ let str = ''
+ for (let prop of this.props) {
+ str += prop.type + ':' + prop.dest + ' '
+ }
+ return str
+ }
+ add(type, dest) {
+ this.props.push(new Property(type, dest))
+ }
+ // recommend hoisting variables when designing them, so they don't match everything
+ has(type, dest) {
+ for (let p of this.props)
+ if ((p.type == type || isVar(type))
+ && (p.dest == dest || isVar(dest)))
+ return true
+ return false
+ }
+ del(type, dest) {
+ for (let i = 0; i < this.props.length; ++ i) {
+ let p = this.props[i]
+ if (p.type == type && p.dest == dest) {
+ this.props.splice(i, 1)
+ return true
+ }
+ }
+ return false
+ }
+ get(type) {
+ let result = null
+ for (let i = 0; i < this.props.length; ++ i) {
+ let p = this.props[i]
+ if (p.type == type) {
+ if (result) throw new Error('get on multiply defined property')
+ result = p.dest
+ }
+ }
+ return result
+ }
+ hasIsVar() {
+ return this.has('is','variable')
+ }
+}
+class AbstractData {
+ constructor(from) {
+ this.props = new Properties('abstract', from && from.props)
+ }
+}
+class StringData extends String {
+ constructor(str, from) {
+ super(str)
+ this.props = new Properties('string', from && from.props)
+ this.props.del('is', 'array')
+ }
+}
+class ArrayData extends Array {
+ constructor(arr, from) {
+ super(...arr)
+ this.props = new Properties('array', from && from.props)
+ this.props.del('is', 'string')
+ }
+}
+
+// Meaning Representation
+class Var extends StringData {
+ constructor(name){
+ super(name)
+ props.add('is','variable')
+ }
+ // recommend e.g. 'is','variable-rep' when code is designing them, so don't match everything
+ // opencog uses a 'quote' wrapper to cause this, sounds more general
+}
+function isVar(x) {
+ return x.props && x.props.has('is','variable')
+}
+const ONE = StringData('one')
+const MANY = StringData('many')
+const VAR_X = new Var('X')
+
+// MEMORY
+// the archivist. Provides for needs of data. Memory is relevent whenever there is
+// an informational need.
+//
+// When remembering steps, likely what is relevent is what is needed to reach the goal
+// Here's a possible step memory.
+//
+// let ret = new StringData('labeled ' + items.length + ' text-string')
+// ret.props.add('is','step-memory')
+// ret.props.add('step',genproptextstring)
+// ret.props.add('ram',ram)
+// ret.props.add('count',items.length)
+// for (let a of items)
+// ret.props.add('item', a)
+
+class ActiveMemory extends ArrayData {
+ // although Memory is eventually a module that provides for stored information needs
+ // this class is just a group of concepts, moved in and out as needed
+ constructor(items, from) {
+ super(items || [], from)
+ this.props.add('is','working-ram')
+ }
+ clone() {
+ return new ActiveMemory(this, this);
+ }
+ add(...items) {
+ //if (this.cloned) { this = this.slice(); this.cloned = false; }
+ for (let item of items)
+ this.push(item)
+ }
+ del(...items) {
+ //if (this.cloned) { this = this.slice(); this.cloned = false; }
+ for (let item of items) {
+ let index = this.indexOf(item)
+ this.splice(index, 1)
+ }
+ }
+ contains(...items) {
+ for (let item of items)
+ if (this.indexOf(item) === -1) return false
+ return true
+ }
+ containsWith(...props) {
+ let ret = []
+ outer: for (let a of this) {
+ for (let i = 0; i < props.length; i += 2)
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ return true
+ }
+ return false
+ }
+ getWith(...props) {
+ let ret = []
+ outer: for (let a of this) {
+ //console.log(a.props.props)
+ for (let i = 0; i < props.length; i += 2) {
+ //console.log(props[i] + ': ' + props[i+1] + '?')
+ if (! a.props.has(props[i], props[i+1]))
+ continue outer
+ }
+ ret.push(a)
+ }
+ if (ret.length > 0) return ret
+ return null
+ }
+}
+// note: for now we produce only data; state-changes are data-changes
+// TODO: this class has methods. turn them into promise-meeting-habits. a promise is a spec for behavior, e.g. how data is stored. this spec can be interpeted by a more general habit.
+class FunctionData {
+ constructor(name, // name of function
+ func, // function taking ordered needs
+ // ordered array of made objects is returned
+ needs, // array of 1-property-per-object this function requires
+ makes // array of 1-property-per-object this function produces
+ ) {
+ this.name = name
+ this.props = new Properties('function')
+ this.props.add('name', name)
+ this.call = func
+ // If needed, make atomspace-like pattern structures for needs/makes.
+ // - represent multiple properties on 1 needed object
+ // - represent input objects present in output
+ this.needs = needs
+ this.makes = makes
+ }
+ makesFrom(ram) { // what we make with the ram
+ // match needs
+
+ // TODO: improve from just picking 1. preferably with relevence.
+ for (let i = 0; i < this.needs.length; i += 2) {
+ if (isVar(this.needs[i]) || isVar(this.needs[i+1])) {
+ // iterate all other options with this? just pick 1?
+ // STUB
+ } else {
+ if (!ram.containsWith(this.needs[i], this.needs[i+1]))
+ return []
+ }
+ }
+ // fill variables STUB
+ }
+ // say I want would-meet apple
+ // and I have needs apple
+ // the easiest way to find this is to fill the needs in with what I have
+}
+
+// variables:
+// - create a place to store a value
+//createvar = new FunctionData(
+// 'createvar',
+// /*call*/(name) => {
+// let ret = new StringData(name)
+// ret.props.add('is','varspec')
+// return ret
+// },
+// /*relevence*/,
+//// when do you want to create a variable? when you need a variable and you have a name
+// /*makes*/
+//)
+// - place a value in such a place
+// - retrieve a value from such a place
+// data-structures: (these are like promises of what to do and how to use something)
+// - make a class definition (collection of variables)
+// - initialize an object
+// - set/retrieve properties (variables)
+// flow:
+// - trigger a different step than the next, conditionally
+// procedures:
+// - collect a set of behaviors together
+// - trigger a collected set of behaviors and continue
+// expressions:
+// - evaluate arithmetic on variables and constants
+
+// sometimes how we get what we need depends on what we have
+line2words = new FunctionData(
+ 'line2words',
+ (line) => { // call
+ let res = new ArrayData(line.split(' '), line)
+ res.props.add('is','words')
+ res.props.del('is','text-string')
+ return res
+ },
+ ['is','text-string'], // needs
+ ['is','word-array'] // makes
+)
+
+// makes text-string used by line2words. example of small relevence habit
+genproptextstring = new FunctionData(
+ 'genproptextstring',
+ /*call*/(text) => {
+ if (text.props.has('is','string')) {
+ if (!text.props.has('is','text-string')) {
+ text.props.add('is','text-string')
+ }
+ return text
+ }
+ return null
+ },
+ /*needs*/['is','text'],
+ /*makes*/['is','text-string']
+)
+
+respondhello = new FunctionData(
+ 'respondhello',
+ (words) => { // call
+ console.log(words[0] + " world!")
+ let res = new StringData("said " + words[0])
+ res.props.add('is','output')
+ res.props.add('is','text')
+ return res
+ },
+ ['is','hello-input'], // needs
+ ['is','output'] // makes
+)
+
+genprophelloinput = new FunctionData(
+ 'genprophelloinput',
+ /*call*/(input) => {
+ if (!input.props.has('is','words'))
+ return null
+ if (!input.props.has('is','hello-input')) {
+ let x = input[0].toLowerCase()
+ let c = x[x.length-1]
+ if (c == ',' || c == '!' || c == '.') x = x.slice(0,x.length-1)
+ if (x != 'hello' && x != 'hi') return null
+ input.props.add('is','hello-input')
+ }
+ return input
+ },
+ /*needs*/['is','input'],
+ /*makes*/['is','hello-input']
+)
+
+/* old, this isn't relevent to needed structure
+// nodejs is missing a succinct read-line-from-stdin function. make our own.
+userinput = (() => {
+ const readline = require('readline')
+ const lines = []
+ readline.createInterface({ input: process.stdin }).on('line', (line) => {
+ lines.push(line)
+ })
+
+ let ret = new FunctionData(
+ 'userinput',
+ (self) => { // call
+ let res = new StringData(lines.shift())
+ res.props.add('is','text')
+ res.props.add('is','input')
+ return res
+ },
+ () => { // relevence
+ return lines.length > 0
+ },
+ ['has','userinput-lines'] // needs
+ ['is','string','is','text','is','input'] // makes
+ )
+ ret.lines = lines
+})()
+genprophaslines = new FunctionData(
+ 'genprophaslines',
+ (userinput) => { // call
+ }
+)
+*/
+
+// PATTERN REQUEST: we want to be able to store needed-steps.
+// needed-steps are parallel needs that are needed for a helpful step
+// any one may be met, and others are ignored once one is, but all are generated at once
+// habits that meet needs expect them not to be inside an array and have no way of referring to that.
+// [AND needs can be collapsed, but OR needs need patterns]
+// [how do we pull a need out of the list?]
+
+// is it useful to use as a need the memory generated by a habit?
+
+// make a habit that plans core behavior
+findstepsfor = new FunctionData(
+ 'findstepsfor',
+ /*call*/(need, depth) => {
+ // find a habit that does the final goal.
+ // TODO: for now we assume all needs are 'is' and store just what-it-is in the need string. when doesn't work anymore, make type-getters on Properties to retrieve the need details
+ let ret = new ArrayData([])
+ for (let habit of all_parts) {
+ if (habit.makes.indexOf(need) !== -1) {
+ // found a workable habit
+ ret.push(habit.needs)
+ }
+ }
+ ret.props.add('is','alternate-needs-array')
+ return ret
+ },
+ // TODO: likely need more structure here
+ // warning: MANY adds surrounding code complexity. please put makes-interpretation in a habit if MANY is used. <- let's just put this in the class constructor for now
+ /*needs*/['needs', VAR_X],
+ /*makes*/[MANY, 'would-meet', VAR_X]
+ // really we are usually met due to the need to meet a goal
+ // and the need to have steps to meet that particular goal
+ // how do we write a need that supports another need
+ //
+ // propose relevence is a list of reasons each with a strength, and greatest sum is chosen
+ // HABIT/ACTIVE BEHAVIOR wants relevent-met-habits, to act on
+ // PLANNING/GOAL BEHAVIOR wants relevent-unmet-needs to backtrace them towards relevent-met-needs
+ //
+ // we can meet any need with behavior, but it takes time.
+ // [we are ignoring most of karl's needs]
+ // [the reason is that an AI can meet them all]
+ // AI meets some needs
+ // AI is ongoing
+ // therefore we are working on meeting
+ // ONE: we have a need for actively pursuing relevent needs
+ // TWO: we need appropriate multitasking
+ // AI is long term, so would happen after [quickly-]meetable-needs are met.
+ //
+ // make popcorn
+ // need: made-popcorn
+ // 1. identify that we need unmade popcorn and a microwave
+ // ^-- made-popcorn is how? we can meet any need with behavior
+ // what is substep of find-path-to-need
+ // find path-part-to-need
+ //
+ // need: to meet needs
+ // need: some-need
+ // makestepsfor makes: some-other-need tagged makes: some-need
+ //
+ // when we push some-need we want to stimulate pushing some-other-need.
+ //
+ // use a variable as the link target, and use e.g. met-need
+ // as the link type
+)
+
+// TODO: add structure enough to build findstepsfor
+// TODO: build findstepsfor
+// TODO 2: add to surrounding process: remove source needs when there is no longer a reason for their presence
+
+
+all_parts = [ line2words, genproptextstring, respondhello, genprophelloinput ]
+
+ram = new ActiveMemory()
+//ram.add(ram)
+optstried = new Set()
+steps = []
+
+var readline = require('readline')
+readline.createInterface({
+ input: process.stdin
+}).on('line', (line) => {
+ line = new StringData(line)
+ line.props.add('is','input')
+ line.props.add('is','text')
+ ram.add(line)
+
+ let cont
+ do {
+ cont = false
+ for (let part of all_parts) {
+ //console.log('for-loop-of-parts ' + part.name)
+ // TODO: >1 parameter,must redo next line
+ let rel = ram.getWith(...part.needs)
+ if (rel) {
+ for (let a of rel) {
+ //console.log('for-loop-of-rel ' + part.name + ' ' + a)
+ if (optstried.has(part.name + ' ' + a)) continue;
+ //console.log('call-part ' + part.name + ' ' + a)
+ res = part.call(a)
+ optstried.add(part.name + ' ' + a)
+ if (res == null) continue
+ // TODO: res==null is considered failure now
+ ram.add(res)
+ //console.log('part-called')
+ step = [a, part.name, res]
+ steps.push(step)
+ console.log('made ' + step)
+ cont = true
+ }
+ }
+ }
+ } while (cont)
+})
+
+
+// it looks like there is a reason to store each item in active memory.
+// one reason is that it is needed by a step in a process.
+// when there are no reasons, it is removed.
+// using an item should link it to what it is used by, so that it may be found easier again when needed
+
+// Please grow to understand your own structure. What is needed to make an intellect?
+// ^-- we want it to learn the basic needs of life, eventually, on its own.
+// notably those to do with care for others.
+
+// MEMORY: see MEMORY above
+
+// RELEVENCE: the gofer. Provides the link between needs, etc, and the behavior that
+// finds them. Is relevent for meeting needs in active ways and likely much else.
+
+// BEHAVIOR: the core. combines interdependent habits from memory to meet needs.
+// The two below go on simultaneously. only 1 is needed.
+// A way to plan behavior:
+// find habits that do the final goal, discern their needs
+// pick needs to treat as a new final goal and repeat until needs are met
+// A way to make behavior:
+// find a habit that does a goal
+// find with this process, information that meets its needs <spawns more>
+// run it
+// TODO: for subprocesses spawning,
+// consider labelling things that are very quick and side-effect-free
+// these can probably be immediately run.
+//
diff --git a/starts/bagel/notes.txt b/starts/bagel/notes.txt
new file mode 100644
index 0000000..18a8f21
--- /dev/null
+++ b/starts/bagel/notes.txt
@@ -0,0 +1,99 @@
+The habits should be used to discern what is relevent; to form relevence.
+The goal should be to choose a relevent habit and do that habit.
+
+These are the basic habits I thought up that a computer program has:
+ variables:
+ - create a place to store a value
+ - place a value in such a place
+ - retrieve a value from such a place
+ data-structures:
+ - make a class definition (collection of variables)
+ - initialize an object
+ - set/retrieve properties (variables)
+ flow:
+ - trigger a different step than the next, conditionally
+ procedures:
+ - collect a set of behaviors together
+ - trigger a collected set of behaviors and continue
+ expressions:
+ - evaluate arithmetic on variables and constants
+
+
+That is:
+========================================================================================================
+ - the active goal is to choose what to do and to what, and do it
+ - the way to do this is the same as it:
+ by picking habits that are relevent in the moment [choose what to do],
+ and running them on relevent data [choose to what, and do it]
+========================================================================================================
+ - the habits should be to identify what is relevent
+
+ - we have a request for the initial goal of the process to be to write a chunk of code out in its own language
+ tighter self-reference is made without the extra sourcecode-file step, but it may be slower to code due to not getting as much help from it
+
+The hope is the process becomes good at active choice.
+
+
+
+Ideas for Tenets for a Need-Based Artificial Life <need ordering + addition + code>
+Behavior is Life <maybe Life is Behavior That Adapts>
+All life has the same core needs. Needs are the reasons to do anything at all.
+We need to know what we want when we act. (all behavior has a reason)
+We need to be able to learn new things.
+We need to be able to make promises on how to behave. (provides for cooperation)
+We need to be able to keep our promises.
+We need to know how to communicate with others what each of us knows.
+We need to freely interact with our friends, our parts, and our community, in ways that we know well. (community is our body)
+Information lives with a reason, a purpose.
+We need to retain the information we choose to retain.
+We need to act to meet our needs.
+We need to identify relevent important needs that support our needs.
+
+We need to be able to try new ways of doing things.
+We need to be able to judge what works.
+
+Proposed Definitions:
+What is an intellect?
+ Propose an intellect is something that can adapt to keep something constant in a diverse, changing environment,
+ so long as the environment changes slowly enough and with enough familiarity for them to learn or prepare effectively.
+What is a full intellect?
+ Propose that a full intellect is an intellect that can design and build something that functions as well as they do,
+ without access to their own workings, and is able to learn to handle arbitrarily fast or new diverse environmental change.
+
+What basic parts do we expect a full intellect to have?
+- Trial Exploration
+- Relevence
+- Self Coding
+- Pattern Generality
+- Meaning Representation
+- Promise Meeting
+
+What other parts do we find we need?
+- Usage Simplification
+
+Trial Exploration
+ Brainstorming, trial-and-error. The ability to try or consider different things and find ones that work well.
+ simple approaches: exhaustive search, and random trial
+
+Relevence
+ The ability to apply concepts and actions moreso in contexts they are likely to be useful than those they aren't.
+ 1. responsiveness for behavior: a habit acts when conditions arise, not when it is 'next'
+ 2. possibly a promise for decision-making, for proposals to have reasons with associated strengths
+ (note: strength appears developed from source reasons and can be missing data that can be filled in by habits when needed)
+ TODO: make relevent decision-making honor convergent needs. maybe strength represents information exchange.
+
+Self-Coding
+ At least part of the system must be fully alterable by the system and generic enough to replace it.
+ Due to the danger involved in this, controversial concerns must be fully included in decisions around it.
+ Karl references Convergent Facilitation as proof that a decision can be found to satisfy any set of controversial concerns.
+ <it very roughly involves rapidly moving towards the reasons of the concerns until they don't conflict; there is a lot of caring dialogue>
+
+Pattern Generality
+ The ability to brainstorm on enough relationships, possibly mathematical, to discover pattern-summaries that are diversely effective in the real world.
+
+Meaning Representation
+ The ability to store and work with conceptual information.
+
+Promise Meeting
+ The ability to make agreements on behavior and structure, adhere to them, and change them when needed.
+