# Representation of agent behavior via a simple vector # BehaviorState.tz (c) 2010 Jacob Schrum. # See Simulation.tz for more copyright information @use Abstract. @include "Constants.tz". @include "ModeArbitrator.tz". Abstract : BehaviorState { + variables: commandline (object). syllabus (list). syllabus-vectors (int). sample-evals (list). sample-times (list). sample-iterator (int). use-min (int). + to show-internal-state: print "syllabus: $syllabus". print "syllabus-vectors: $syllabus-vectors". print "sample-evals: $sample-evals". print "sample-times: $sample-times". print "sample-iterator: $sample-iterator". + to init: use-min = 0. + to give-syllabus these inputs (list): free syllabus. syllabus = inputs. + to clear-syllabus: self give-syllabus these {}. + to add-syllabus inputs v (list): if (|syllabus| < syllabus-vectors) : { #print "Behavior vector $sample-iterator : eval ", sample-evals{sample-iterator}, ", time ", sample-times{sample-iterator}, ": ", v. sample-iterator++. push v onto syllabus. } else { print "ERROR: tried to add more syllabus input vectors than desired". (controller end-simulation). return. } + to get-current-sample-eval: if (sample-iterator < |sample-evals|) : return sample-evals{sample-iterator}. else return -1. + to get-current-sample-time: if (sample-iterator < |sample-times|) : return sample-times{sample-iterator}. else return -1. # Pre conditions: # - Only call during a parent eval stage # Post conditions: # - sample-evals sorted in increasing order # - if two or more consecutive values of sample-evals are the same, # then the sequence of values in sample-times at the same indexes # should also be sorted in increasing order + to determine-observed-syllabus-sample-points: total-evals (int). time-steps (int). i (int). temp (int). time-steps = (commandline num-param named "eval-iterations"). total-evals = (controller get-real-num-evals). free syllabus. syllabus = {}. free sample-evals. sample-evals = {}. free sample-times. sample-times = {}. for i = 0, i < syllabus-vectors, i++ : { temp = random[ (total-evals - 1) ]. push temp onto sample-evals. } # So chosen evals match the order in which they occur ((controller get-list-ops) ascending-sort the-list sample-evals). for i = 0, i < syllabus-vectors, i = |sample-times| : { temp = random[ (time-steps - 1) ]. push temp onto sample-times. # Assure the second post condition holds while (i > 0) && (sample-evals{i} == sample-evals{(i - 1)}) && (sample-times{i} < sample-times{(i - 1)}) : { temp = sample-times{i}. sample-times{i} = sample-times{(i - 1)}. sample-times{(i - 1)} = temp. i--. } } # Set iterator to start position sample-iterator = 0. + to randomize-syllabus length len (int): i (int). j (int). tempList (list). tempList = {}. for i = 0, i < syllabus-vectors, i++ : { push {} onto tempList. for j = 0, j < len, j++ : { # Most inputs are constrained by this range. # Still not the most ideal input set. push (random[(2 * PI)] - PI) onto tempList{i}. } } #print tempList. self give-syllabus these tempList. + to give-commandline this cl (object): commandline = cl. syllabus-vectors = (commandline num-param named "num-behavior-syllabus-vectors"). use-min = (commandline bit-param named "min-behavior-diversity"). + to compare-network-modes network net (object) mode m1 (int) and m2 (int): b1 (list). b2 (list). b1 = (self get-network-behavior-vector network net choose m1). b2 = (self get-network-behavior-vector network net choose m2). return ((controller get-math) get-euclidean-distance between b1 and b2). # Get behavior vector of network. # Optionally, get the behavior vector using output mode "mode" instead of # using the best mode (default value -1). # - net: the neural network. # - mode: -1 => Choose best output mode of network for each input. # else => always pick designated mode of network regardless of best choice. + to get-network-behavior-vector network net (object) choose mode = -1 (int): i (int). j (int). outputs (list). behavior (list). for i = 0, i < |syllabus|, i++ : { net run-with inputs (syllabus{i}). outputs = {}. for j = 0, j < (net get-number-outputs), j++ : { push (net get-output at-position j) onto outputs. } if (mode == -1) : { # Returns pair of {mode num, mode outputs} outputs = ((controller get-mode-arbitrator) net-outputs-of outputs outputs). outputs = outputs{ARBITRATE_OUTPUT}. } else outputs = ((controller get-mode-arbitrator) mode-outputs-of outputs outputs mode mode). for j = 0, j < |outputs|, j++ : { push (outputs{j}) onto behavior. } } #print "Behavior vector: $behavior". return behavior. # Get behavior vector of monster at position pos in monsters list. # Optionally, get the behavior vector using output mode "mode" instead of # using the best mode (default value -1). # - monsters: list of monsters in game. # - pos: index in monsters. # - mode: -1 => Choose best output mode of network for each input. # else => always pick designated mode of network regardless of best choice. + to get-behavior-vector given monsters (list) index-of pos (int) choose mode = -1 (int): behavior (list). # TODO: # - syllabus planned in advance # Arbitration by cases is only needed if there is ever a method that does not use a syllabus behavior = (self get-network-behavior-vector network (monsters{pos} extract-genome) choose mode). return behavior. + to get-average-euclidean-distance of pos (int) within behavior-vectors (list): sum (double). k (int). sum = 0. # Compare to every other individual for k = 0, k < |behavior-vectors|, k++ : { if (pos != k) : { sum += ((controller get-math) get-euclidean-distance between (behavior-vectors{pos}) and (behavior-vectors{k})). } } return (sum / (|behavior-vectors| - 1)). + to get-min-euclidean-distance of pos (int) within behavior-vectors (list): minD (double). k (int). minD = INFINITY. # Compare to every other individual for k = 0, k < |behavior-vectors|, k++ : { if (pos != k) : { minD = min( minD, ((controller get-math) get-euclidean-distance between (behavior-vectors{pos}) and (behavior-vectors{k})) ). } } return minD. + to get-behavioral-diversity-score of pos (int) within behavior-vectors (list): if (use-min) : { return (self get-min-euclidean-distance of pos within behavior-vectors). } else { return (self get-average-euclidean-distance of pos within behavior-vectors). } }