#] #]******************************************************* #] loaddefs link d_Qndfs 'MindCode/MindCode basics.ndf' - # www.BillHowell.ca 22Feb2020 initial # view this file with tabs=3 spaces, constant-width font, full screen output # header - [architectures, rules] for MindCode neuron - with [DNA-mRNA-epi, addressable synapses] # 14Mar2020 Note that MindCode naturally provides a programming environment that is highly : # [parallel, multi-[objective, process, networked-hierarchical, threaded-like]] # MindCode - some key [stages, areas] that are targeted : # 1. now : [architecture, data, functions, processes, operating systems] # 2. in 3-6 months : [fixed, parametric, learning, evolution (Lamarckian & Mendellian), hyper-evolution] # 3. in 3-5 years? : [conciousness, behaviours, personalities, creativity, social] # [emotion, depression, anxiety, stress] # [von Neuman, sequential, Z80 micro-processor] coding basis, # view this file in a text editor, with [constant width font, tab = 3 spaces] # human sensory is quite sensitive, for now assume ~256 range = 8 bit analogue equivalent (2^8 = 1 byte) # The [data, operators] below are definite "cheats" from basic computer programming, # and are probably very unlike actual representations in biology!! # However, programmers used to dealing with bit-wise operations should find this [easy, clear]. # Note: All [data, operators] are by default "Z80" (like 8-bit microprocessor of yester-year) # Alternate more bio-realistic nets can be switched in by defining them just below the Z80 definitions # [and, or] by using comment statements "#" f_MindCode_basics := 'MindCode/MindCode basics.ndf' ; loaddefs_start f_MindCode_basics ; #******************************************************* # List of operators, see : # $ cat "$d_Qndfs""MindCode/MindCode basics.ndf" | grep "^#]" | sed 's/^#\]/ /' ******************************************************* loaddefs link d_Qndfs 'MindCode/MindCode basics.ndf' - +-----+ build MindCode global [network, cols] local_to_global_cols IS - based on all sub_nets loadded, adapt local-to-global indexing nmID_to_ID IS OP nmID - given the nmID=[nameL, IDsubL], find the stdID stdInOutTrig IS - build stdOutL list of (each net [input, output, trgrPat] connections) stndNet_build IS - add n_cols of of "standard" cnstNet data to corresponding globalCols of MindCode +-----+ fire [sensory, netID fire IS OP netID - fire netID (of lastFireL nets), using its optr +-----+ MindCode [stop, cycle, load, test] MindCode_stop IS - output the final results MindCode_cycle IS - fire appropriate neurons, then update the net MindCode_load IS - load all sub-nets MindCode_tests IS - collection of standard checks that operators function as expected MindCode_cycle load MindCode ; #*********************************** # Debugging setup and reminders # see link d_QNial_root '0_bug hunt QNial.txt' log_out := 'stdout' ; %log_out := 'file' ; # 30Apr2020 for later, can't get p_log to work IF (= log_out 'stdout') THEN p_log := 1 ; ELSE p_log := open (link d_Qndfs 'MindCode/code test/test log.txt') "w ; ENDIF ; # write filestatus ; # write link 'p_log= ' (string p_log) ; flag_break := o ; setwidth 235 ; loaddefs link d_Qndfs 'MindCode/globals initialize.ndf' ; loaddefs link d_Qndfs 'MindCode/data types.ndf' ; loaddefs link d_Qndfs 'MindCode/trigger patterns.ndf' ; loaddefs link d_Qndfs 'MindCode/bits to-from [intg, real].ndf' ; #loaddefs link d_Qndfs 'MindCode/net constructors.ndf' ; #] +-----+ #] build MindCode global [network, cols] # 14Mar2020 MindCode currently is capable of running only ONE instance per QNial seession # this is because a common set of global variable used # To run multiple MindCodes simulataneously - run separate instances of QNial in different terminals IF flag_debug THEN write '+-----+' ; ENDIF ; IF flag_debug THEN write 'build MindCode global [network, cols]' ; ENDIF ; IF flag_debug THEN write 'loading local_to_global_cols' ; ENDIF ; #] local_to_global_cols IS - based on all sub_nets loadded, adapt local-to-global indexing local_to_global_cols IS { NONLOCAL net_rows IDL inL outL trgrPatL histPatL histPatNowL OKL ; IDL := tell net_rows ; inL := reshape net_rows (solitary null) ; outL := inL ; trgrPatL := inL ; histPatL := inL ; histPatNowL := inL ; OKL := inL ; } IF flag_debug THEN write 'loading nmID_to_ID' ; ENDIF ; #] nmID_to_ID IS OP nmID - given the nmID=[nameL, IDsubL], find the stdID nmID_to_ID IS OP name IDsub { LOCAL i ; NONLOCAL XrefNmL XrefIDsubL XrefIDL ; i := find_Howell name XrefNmL ; first ((IDsub EACHRIGHT = XrefIDsubL@i) sublist XrefIDL@i) } # tests - shows that I must "solitary" any simple nmIDs # Good : # nmID_to_ID ("real00_str 0) # EACH nmID_to_ID (("real00_sns 1) ("real00_sns 2)) # EACH nmID_to_ID (("real00_sns 4) ("real00_sns 5) ("real00_str 0) ("real00_str 1)) # TWIG nmID_to_ID ("real00_str 0) # TWIG nmID_to_ID (sol ("real00_str 0)) # TWIG nmID_to_ID (sol ("real00_str 0)) # TWIG nmID_to_ID (sol (("real00_sns 4) ("real00_sns 5) ("real00_str 0) ("real00_str 1))) # TWIG nmID_to_ID (("real00_sns 1) ("real00_sns 2) (("real00_sns 4) ("real00_sns 5) ("real00_str 1))) # Bad : # nmID_to_ID (sol ("real00_str 0)) # EACH nmID_to_ID (sol (("real00_sns 4) ("real00_sns 5) ("real00_str 0) ("real00_str 1))) # EACH nmID_to_ID (("real00_sns 1) ("real00_sns 2) (("real00_sns 4) ("real00_sns 5) ("real00_str 0) ("real00_str 1))) IF flag_debug THEN write 'loading stdInOutTrig' ; ENDIF ; #] stdInOutTrig IS - build stdOutL list of (each net [input, output, trgrPat] connections) # 22Mar2020 need to adapt this to arbitrary subNets! # 23Mar2020 this is very inefficient! # there are >=1 stdInNmIDL@stdID in general ; # 24Mar2020 it might be faster for small networks to simply sublist on [nameL, IDL] directly ; # loaddefs link d_Qndfs 'MindCode/MindCode basics.ndf' IF flag_break THEN BREAK ; ENDIF ; stdInOutTrig IS { LOCAL i stdID IDstdIDs inNet inNmID selection ; NONLOCAL IDL nameL IDsubL inNmIDL inL outL trgrPatNmIDL trgrPatL Xref_rows XrefNmL XrefIDsubL XrefIDL ; % ; % build [nameL, IDsubL] cross-reference ; XrefNmL := cull sortup nameL ; Xref_rows := gage shape XrefNmL ; XrefIDsubL := Xref_rows reshape null ; XrefIDL := XrefIDsubL ; FOR i WITH (tell Xref_rows) DO selection := XrefNmL@i EACHRIGHT = nameL ; XrefIDsubL@i := selection sublist IDsubL ; XrefIDL@i := selection sublist IDL ; ENDFOR ; % ; % build inL ; FOR ID WITH IDL DO IF (~= null inNmIDL@ID) THEN inL@ID := link inL@ID (TWIG nmID_to_ID inNmIDL@ID) ; ENDIF ; ENDFOR ; inL := EACH link inL ; % ; % build OutL ; FOR ID WITH IDL DO IF (~= null IDL@ID) THEN FOR inNet WITH inL@ID DO outL@inNet := link outL@inNet ID ; ENDFOR ; ENDIF ; ENDFOR ; % ; % build trgrPatL ; FOR ID WITH IDL DO IF (~= null trgrPatNmIDL@ID) THEN trgrPatL@ID := link trgrPatL@ID (TWIG nmID_to_ID trgrPatNmIDL@ID) ; ENDIF ; ENDFOR ; } # tests IF flag_debug THEN write 'loading stndNet_build' ; ENDIF ; #] stndNet_build IS - add n_cols of of "standard" cnstNet data to corresponding globalCols of MindCode stndNet_build IS { LOCAL n_rows n_cols subCols titles ; NONLOCAL subTemp ; n_cols := 15 ; n_rows := floor ((gage shape subTemp) / n_cols) ; subTemp := n_rows n_cols reshape subTemp ; titles := subTemp|[0,] ; subCols := cols subTemp|[count (n_rows - 1),] ; titles EACHBOTH assign ((EACH execute titles) EACHBOTH link subCols) ; } #] +-----+ #] fire [sensory, netID # fire IS OP netID - many extra comments # normally, used with inNets of same [type, use], and in any order # this ASSUMES that the end-of-time-interval operations have properly adjusted and net data # this can ALSO be used for multiple inNets of DIFFERENT [type, use] if they are ordered properly # example power : there must be TWO inNets, the first provides the base, the second provides the exponent # this can be checked during data setup # this is completely divorced from biology! however, it's a start until specalized nets are developed # Pre-declare so these don't cause problems : # need approaches for [neuro-modulators, solarEMF, glial] # probably vastly different from "fire" # check if oprtr is OK for type? Don't need to, as a fault will result if not? ; # firing rules - several rules may give co-incidental fire orders - raises issue of "ambiguous output" # perhaps - the greater the [diversity, length] of a trigger, the more [robust, specific] the responses # nyet - histPatL takes care of this? # 14Mar2020 WRONG! - need # nowFireL that accumulates all current firing for each netID # lastFireL that is used for fire # then MindCode_cycle must # link histPatL := link (solitary nowFireL) (rest histPatL) # lastFireL := nowFireL, nowFireL:= null # real out of range - I'll have to figure out what to do with this - espectialy with only 7 bits (+-) % current firing is ONLY based on the LAST timestep, plus exogenous inputs ; % i.e. current firing does NOT affect firing of other nets in this timestep, only in the next timestep ; IF flag_debug THEN write '+-----+' ; ENDIF ; IF flag_debug THEN write 'examples' ; ENDIF ; IF flag_debug THEN write 'loading fire' ; ENDIF ; #] fire IS OP netID - fire netID (of lastFireL nets), using its optr # 14Mar2020 IMPORTANT! nets know which netIDs signal them, but at this stage # cannot select destination netIDs that will receive their firing, # from among those connected downstream via axon # 25Mar2020 inconsistency - fire updates fireL, but other nets should be using the previous value # 01Apr2020 I am missing the trigger testing! IF flag_break THEN BREAK ; ENDIF ; IF (= netID 11) THEN BREAK ; ENDIF ; fire IS OP netID { LOCAL fires ; NONLOCAL fireL inL opL typeL trgrTyp trgrPatL histPatL nowFireL ; % 28Feb2020 neuromodulator changes - not yet implemented ; % 04Mar2020 missing time delays (eg STDP), 06Mar2020 can be in trgrPatL!!! ; IF (= 'sens' opL@netID) THEN nowFireL := link nowFireL netID ; % later, nowFireL is used to update [TwaitL, histPatL, etc] ; ELSE IF (apply trgrTypL@netID (trgrPatL@netID histPatL@netID)) THEN fires := fireL#(inL@netID) ; IF (= 's2i' opL@netID) THEN fireL@netID := spikes_to_intg first fires ; nowFireL := link nowFireL netID ; ELSEIF (= 's2r' opL@netID) THEN fireL@netID := spikes_to_real first fires ; nowFireL := link nowFireL netID ; ELSEIF (= 'bool' typeL@netID) THEN fireL@netID := apply opL@netID fires ; nowFireL := link nowFireL netID ; ELSEIF (= 'intg' typeL@netID) THEN fireL@netID := intg_to_spikes (apply opL@netID (EACH spikes_to_intg fires)) ; nowFireL := link nowFireL netID ; ELSEIF (= 'real' typeL@netID) THEN fireL@netID := real_to_spikes (apply opL@netID (EACH spikes_to_real fires)) ; nowFireL := link nowFireL netID ; ELSE write fault '?E_base01' ; ENDIF ; ENDIF ; % later, nowFireL is used to update [ToffL, histPatL, etc] ; ENDIF ; } #] +-----+ #] MindCode [stop, cycle, load, test] IF flag_debug THEN write '+-----+' ; ENDIF ; IF flag_debug THEN write 'MindCode [stop, cycle, load, test]' ; ENDIF ; IF flag_debug THEN write 'loading MindCode_stop' ; ENDIF ; #] MindCode_stop IS - output the final results MindCode_stop IS { NONLOCAL IDL OKL ; null ; % do these in the test files ; % 02Apr2020 - [std results, writes] are usually specified in the test ndfs ; } IF flag_debug THEN write 'loading MindCode_cycle' ; ENDIF ; #] MindCode_cycle IS - fire appropriate neurons, then update the net # ['ToffL', 'TwaitL'] can dramatically affect results # example : [sin, cos] if fired at times ~= period, could show [constant, erratic] outputs # must be able to choose from available input nets # currently I'm not trying to make this more efficient by firing only netIDs with least some inputs % 04Mar2020 for now, assume that if ALL inNmIDLs are in nowFireL, then fire ; # 04Mar2020 delayed firing inputs are required (eg STDP) # 14Mar2020 at present - no [ontogeny, learning, evolution] MindCode_cycle IS { LOCAL flag_continue i i_cycle netID ; NONLOCAL cycle_max flag_cycle_output out outs TwaitL net_rows IDL histPatL histPatNowL trgrPatL nowFireL ; % ; flag_continue := l ; i_cycle := 0 ; WHILE flag_continue DO % sensory nets - as per "Twaits", fire all sensory ("sens") nets ; FOR i WITH sensIDL DO fire i ; ENDFOR ; % ; % inSeries - 04Mar2020 add later ; % firing of the netMindCode-affected inputs (eg. for [control, real-time, etc]) ; % inFeedback - 04Mar2020 add later, but is automatic for any nets, its just exogenous variables that still need to be addressed ; % ; % try firing all neurons with Twait = 0, of course firing doesn't happen unless the trigger patters are satisfied ; FOR netID WITH IDL DO IF (= 0 TwaitL@netID) THEN fire netID ; ELSE TwaitL@netID := TwaitL@netID - 1 ; ENDIF ; ENDFOR ; % ; % histPatNowL - ensure each is a list (eg solitary atoms), update histPatNowL ; % 27Mar2020 the length of histPatL@netID is capped by its initial shape!! (minum two by technicality) ; nowFireL := cull sortup nowFireL ; % 01Apr2020 each net can only fire once, but easier to examine ; FOR netID WITH nowFireL DO outs := outL@netID ; FOR out WITH outs DO histPatNowL@out := link histPatNowL@out netID ; ENDFOR ; ENDFOR ; % ; % update histPatL to be ready for the next cycle ; % 01Apr2020 may have to remove double firing? (shouldn't happen) ; FOR netID WITH IDL DO IF (= null histPatNowL@netID) THEN histPatL@netID := link (solitary null) (front histPatL@netID) ; ELSE histPatL@netID := link (solitary histPatNowL@netID) (front histPatL@netID) ; ENDIF ; ENDFOR ; % ; % optional output during cycle - specialised versions are used for specific tests, so un-comment those desired ; % 02Apr2020 turn the off for now ... ; % write link 'cycle# = ' (string i_cycle) ; % write 'nowFireL= ' nowFireL ; % titles := 'IDL' 'TwaitL' 'histPatNowL' 'histPatL' 'trgrPatL' ; % write transpose mix ((EACH solitary titles) EACHBOTH link (EACH execute titles)) ; % ; % update [nowFireL, histPatL, histPatNowL] to be ready for the next cycle ; nowFireL := null ; histPatNowL := net_rows reshape (solitary null) ; % ; % check for continue conditions ; % stop may occur when net output has reached some kind of end-point - 04Mar2020 for much later in development ; i_cycle := i_cycle + 1 ; IF (i_cycle >= cycle_max) THEN flag_continue := o ; ENDIF ; % change to REPEAT loop ; ENDWHILE ; MindCode_stop ; } IF flag_debug THEN write 'loading MindCode_load' ; ENDIF ; #] MindCode_load IS - load all sub-nets # 16Mar2020 MISSING : "tie-ins" between sub-nets!!! MindCode_load IS { NONLOCAL net_rows IDsubL sensIDL ; loaddefs link d_Qndfs 'MindCode/error codes.ndf' ; initGlobals ; % initialise global variables ; loaddefs link d_Qndfs 'MindCode/arith, trig examples.ndf' ; net_rows := gage shape IDsubL ; % ; local_to_global_cols ; % build extra columns based on all sub_nets loadded ; stdInOutTrig ; % build [inL, outL] list of (each net [input, output] connections in terms of IDL) ; sensIDL := ('sens' EACHRIGHT = opL) sublist IDL ; % histPatL@ID must be preset to the length of trgrPatL@ID ; FOR ID WITH (tell net_rows) DO histPatL@ID := (gage shape trgrPatL@ID) reshape (solitary null) ; ENDFOR ; } # tests - In general, these are copied over from various examples # each example must be loaddefed first in MindCode_load above (eg 'arith, trig examples.ndf') IF flag_debug THEN write 'loading MindCode_tests' ; ENDIF ; #] MindCode_tests IS - collection of standard checks that operators function as expected # tests are specific to a given MindCode (network) MindCode_tests IS { LOCAL d_MindCode_tests ; d_MindCode_tests := link d_Qndfs 'MindCode/code test/' ; % from 'arith, trig examples.ndf' ; loaddefs link d_MindCode_tests 'bits to-from [intg, real] tests.ndf' ; loaddefs link d_MindCode_tests 'index tests.ndf' ; loaddefs link d_MindCode_tests 'trigger [now, cum, seq, tim, mix] tests.ndf' ; loaddefs link d_MindCode_tests 'fire tests.ndf' ; } IF flag_debug THEN write 'loading MindCode_cycle' ; ENDIF ; #] MindCode_cycle # close log file - this should be done manually? IF (= log_out 'file') THEN close p_log ; ENDIF ; #********************************* #] load MindCode ; IF flag_debug THEN write '+-----+' ; ENDIF ; IF flag_debug THEN write 'load MindCode' ; ENDIF ; # loaddefs link d_Qndfs 'MindCode/MindCode basics.ndf' MindCode_load ; loaddefs_ended f_MindCode_basics ; # enddoc