def test_runN(self): """ Test running for N turns. """ new_env = Env("Test1 env", action=env_action, members=[self.newton]) num_periods = 10 acts = new_env.runN(num_periods) self.assertEqual(acts, num_periods)
def test_tcall(self): # need special env for this one env = Env("Test env", members=[create_newton()], exec_key=self.exec_key) acts = run(self.test_user, test_run=True) self.assertEqual(acts, DEF_STEPS)
def test_restore_env(self): """ This test depends upon a particular, stored json format: must be re-written. """ tests_env = env_json_basic.ret() ret_env = Env("env", serial_obj=tests_env) self.assertEqual(str(type(ret_env)), "<class 'indra.env.Env'>")
def setUp(self): self.exec_key = get_exec_key() self.env = Env("test_env", exec_key=self.exec_key) (self.space, self.newton) = create_space(self.exec_key) self.test_agent = Agent("test agent", exec_key=self.exec_key) self.test_agent2 = Agent("test agent 2", exec_key=self.exec_key) self.test_agent3 = Agent("test agent 3", exec_key=self.exec_key) self.test_agent4 = Agent("test agent 4", exec_key=self.exec_key)
def __json_to_object(self, serial_obj, exec_key): """ Takes a serial JSON object back into a live Python object. """ restored_obj = dict() restored_groups = [] model_deserialized = False for obj_name in serial_obj: should_restore_object = isinstance(serial_obj[obj_name], dict) and "type" in serial_obj[ obj_name] if should_restore_object: if serial_obj[obj_name]["type"] == "TestUser": restored_obj[obj_name] = TermUser(name=obj_name, serial_obj=serial_obj[ obj_name], exec_key=exec_key) if serial_obj[obj_name]["type"] == "APIUser": restored_obj[obj_name] = APIUser(name=obj_name, serial_obj=serial_obj[ obj_name], exec_key=exec_key) if serial_obj[obj_name]["type"] == "Agent": restored_obj[obj_name] = Agent(name=obj_name, serial_obj=serial_obj[ obj_name], exec_key=exec_key) elif serial_obj[obj_name]["type"] == "Model": from lib.model import Model print(f'restoring model for key {exec_key}') restored_obj[obj_name] = Model(exec_key=exec_key, serial_obj=serial_obj[ obj_name]) model_deserialized = True elif serial_obj[obj_name]["type"] == "Group": from lib.group import Group restored_obj[obj_name] = Group(exec_key=exec_key, serial_obj=serial_obj[ obj_name], name=serial_obj[obj_name][ 'name']) restored_groups.append(restored_obj[obj_name]) elif serial_obj[obj_name]["type"] == "Env": restored_obj[obj_name] = Env(exec_key=exec_key, serial_obj=serial_obj[ obj_name], name=serial_obj[obj_name][ 'name']) else: restored_obj[obj_name] = serial_obj[obj_name] self.registries[exec_key][obj_name] = restored_obj[obj_name] if model_deserialized: restored_obj['model'].groups = restored_groups restored_obj['model'].env = restored_obj['env'] self.registries[exec_key]['model'] = restored_obj['model'] return restored_obj
def create_env(self, env_action=None, random_placing=True): """ Override this method to create a unique env... but this one will already set the model name and add the groups. """ # NOTE: WE DEFAULT TO RANDOM PLACING ALL THE TIME # EVEN FOR MODELS LIKE FOREST FIRE self.env = Env(self.module, members=self.groups, exec_key=self.exec_key, width=self.width, height=self.height, action=env_action, random_placing=random_placing) self.env.user = self.user self.env.user_type = self.user_type self.create_pop_hist() return self.env
def __init__(self, status, headers={}, tpl=None): # get http status code's from json hsc = open('config/http_status_codes.json') jhsc = json.load(hsc) # view params params = {'key': status, 'value': ''} params['SERVER_NAME'] = Env.get('SERVER_NAME') params['CONTACT'] = Env.get('CONTACT') params['SERVER_SOFTWARE'] = Env.get('SERVER_SOFTWARE') # status exists in json if status in jhsc: params['value'] = jhsc[status] # status tpl if tpl==None: tpl = "error/"+status+".tpl" # Content type required header if 'Content-Type' in headers: pass else: headers['Content-Type'] = 'text/html' # load view data = View.load(tpl, params) # view not exists, load default tpl if data==False: tpl = 'error/default.tpl' data = View.load(tpl, params) msg = "\nzpy Error: \n" msg += "Status: "+status+"\n" msg += "Url: "+Env.get('REQUEST_URI')+"\n" msg += "Remote Address: "+Env.get('REMOTE_ADDR')+"\n" msg += "Date: "+time.strftime("%Y/%m/%d %H:%M:%S")+"\n" msg += "-------------------------------------------" Log.debug(msg) web.HTTPError.__init__(self, status, headers, data)
def test_image_speed(self): from lib.env import Env from lib.paramenters import Parameters import lib.other_agent as other_agent pa = Parameters() pa.simu_len = 50 pa.num_ex = 10 pa.new_job_rate = 0.3 pa.compute_dependent_parameters() env = Env(pa, render=False, repre='image') import time start_time = time.time() for i in range(100000): a = other_agent.get_sjf_action(env.machine, env.job_slot) env.step(a) end_time = time.time() print("- Elapsed time: ", end_time - start_time, "sec -")
def test_plot_data(self): """ Test the construction of scatter plot data. """ global travis travis = os.getenv("TRAVIS") if not travis: our_grp = Group(GRP1, members=[self.newton], exec_key=self.exec_key) self.env = Env("Test env", members=[our_grp], exec_key=self.exec_key) ret = self.env.plot_data() (x, y) = self.newton.pos self.assertEqual( ret, {GRP1: { X: [x], Y: [y], 'color': None, 'marker': None }})
def from_json(self, jrep): """ This method restores a model from its JSON rep. """ self.module = jrep["module"] self.exec_key = jrep["exec_key"] self.period = jrep["period"] self.switches = jrep["switches"] # We should restore user from json: # self.user = jrep["user"] # But for the moment we will hard code this: self.user = APIUser(model=self, name="API", exec_key=self.exec_key, serial_obj=jrep["user"]) self.user_type = jrep["user_type"] self.props = jrep["props"] self.env = Env(self.module, serial_obj=jrep["env"], exec_key=self.exec_key) # since self.groups is a list and self.env.members is an OrderedDict self.groups = [ self.env.members[group_nm] for group_nm in self.env.members ]
class EnvTestCase(TestCase): def setUp(self): self.exec_key = get_exec_key() self.newton = create_newton() self.calcs = create_calcguys(self.exec_key, []) self.cambs = create_cambguys(self.exec_key) self.pop_hist = PopHist() self.model = Model(exec_key=self.exec_key) self.env = self.model.env self.env.action = env_action # Env("Test env", action=env_action, exec_key=self.exec_key) def tearDown(self): self.exec_key = None self.newton = None self.calcs = None self.cambs = None self.pop_hist = None self.env = None def fill_pop_hist(self): self.pop_hist.record_pop(GRP1, 10) self.pop_hist.record_pop(GRP2, 10) self.pop_hist.record_pop(GRP1, 20) self.pop_hist.record_pop(GRP2, 20) return self.pop_hist def test_user_type(self): """ Make sure our user type is test. API is the new default user_type """ user_type = os.getenv('user_type', API) self.assertEqual(self.env.user_type, user_type) @skip("This test awaits new registry.") def test_runN(self): """ Test running for N turns. """ new_env = Env("Test1 env", action=env_action, members=[self.newton]) num_periods = 10 acts = new_env.runN(num_periods) self.assertEqual(acts, num_periods) def test_str_pop(self): """ Test converting the pop history to a string. """ self.fill_pop_hist() s = str(self.pop_hist) self.assertEqual(s, POP_HIST_HDR + GRP1 + POP_SEP + GRP2 + POP_SEP) def test_record_pop(self): self.assertTrue(True) @skip("This now works differently and the test needs to be re-written") def test_add_child(self): self.env.add_child(self.newton, self.calcs) self.assertIn((self.newton, self.calcs), self.env.womb) def test_has_disp(self): if not disp.plt_present: self.assertTrue(not self.env.has_disp()) else: self.assertTrue(self.env.has_disp()) def test_line_data(self): """ Test the construction of line graph data. """ global travis travis = os.getenv("TRAVIS") if not travis: self.env.pop_hist = self.fill_pop_hist() ret = self.env.line_data() self.assertIn(GRP1, ret[1]) self.assertIn(GRP2, ret[1]) # we should test that the color vals are in our list of colors self.assertIn("color", ret[1][GRP1]) self.assertIn("color", ret[1][GRP2]) # we should test that the data is a list of ints self.assertIn("data", ret[1][GRP1]) self.assertIn("data", ret[1][GRP2]) @skip( "Some problem with returned plot data: also test is too coupled to code." ) def test_plot_data(self): """ Test the construction of scatter plot data. """ global travis travis = os.getenv("TRAVIS") if not travis: our_grp = Group(GRP1, members=[self.newton], exec_key=self.exec_key) self.env = Env("Test env", members=[our_grp], exec_key=self.exec_key) ret = self.env.plot_data() (x, y) = self.newton.pos self.assertEqual( ret, {GRP1: { X: [x], Y: [y], 'color': None, 'marker': None }}) def test_headless(self): if (self.env.user_type == API) or (self.env.user_type == TEST): self.assertTrue(self.env.headless()) else: self.assertTrue(not self.env.headless()) def test_env_action(self): self.env() self.assertEqual(self.env.duration, ENV_ACT_RET) @skip def test_restore_env(self): """ This test depends upon a particular, stored json format: must be re-written. """ tests_env = env_json_basic.ret() ret_env = Env("env", serial_obj=tests_env) self.assertEqual(str(type(ret_env)), "<class 'indra.env.Env'>")
def test_backlog(self): from lib.env import Env from lib.paramenters import Parameters import lib.other_agent as other_agent pa = Parameters() pa.num_nw = 5 pa.simu_len = 50 pa.num_ex = 10 pa.new_job_rate = 1 pa.compute_dependent_parameters() env = Env(pa, render=False, repre='image') env.step(5) env.step(5) env.step(5) env.step(5) env.step(5) env.step(5) # self.assertIsNotNone(env.job_backlog.backlog[0]) # self.assertIsNone(env.job_backlog.backlog[1]) print("New job is backlogged.") env.step(5) env.step(5) env.step(5) env.step(5) job = env.job_backlog.backlog[0] env.step(0) self.assertEqual(env.job_slot.slot[0], job) # assert env.job_slot.slot[0] == job job = env.job_backlog.backlog[0] env.step(0) self.assertEqual(env.job_slot.slot[0], job) # assert env.job_slot.slot[0] == job job = env.job_backlog.backlog[0] env.step(1) self.assertEqual(env.job_slot.slot[1], job) job = env.job_backlog.backlog[0] env.step(1) self.assertEqual(env.job_slot.slot[1], job) env.step(5) job = env.job_backlog.backlog[0] env.step(3) # self.assertEqual(env.job_slot.slot[3],job ) print("- Backlog test passed -")
class Model(): """ This class is the base class for all Indra models. It will have all of the basic methods a model needs, as well as a `run()` method that will kick of the model, display the menu (if on a terminal), and register all methods necessary to be registered for the API server to work properly. It should also make the notebook generator much simpler, since the class methods will necessarily be present. """ # NOTE: random_placing needs to be handled on the API side def __init__(self, model_nm="BaseModel", props=None, grp_struct=DEF_GRP_STRUCT, env_action=None, random_placing=True, serial_obj=None, exec_key=None, create_for_test=False): self.num_switches = 0 if serial_obj is None: self.create_anew(model_nm, props, grp_struct, exec_key, env_action, random_placing, create_for_test) else: self.create_from_serial_obj(serial_obj) def create_anew(self, model_nm, props, grp_struct, exec_key, env_action, random_placing, create_for_test=False): """ Create the model for the first time. """ self.module = model_nm self.grp_struct = grp_struct self.handle_props(props) if exec_key is not None: self.exec_key = exec_key elif self.props.get("exec_key", None) is not None: self.exec_key = self.props.get("exec_key") else: self.exec_key = registry.create_exec_env( create_for_test=create_for_test) self.create_user() registry.reg_model(self, self.exec_key) self.groups = self.create_groups() self.env = self.create_env(env_action=env_action, random_placing=random_placing) self.switches = [] # for agents waiting to switch groups self.period = 0 def handle_props(self, props, model_dir=None): self.user_type = os.getenv("user_type", API) if self.user_type == API: self.props = init_props(self.module, props, model_dir=model_dir, skip_user_questions=True) else: self.props = init_props(self.module, props, model_dir=model_dir) self.height = self.props.get(GRID_HEIGHT, DEF_HEIGHT) self.width = self.props.get(GRID_WIDTH, DEF_WIDTH) def create_from_serial_obj(self, serial_obj): """ Restore the model from its serialized version. """ self.from_json(serial_obj) def from_json(self, jrep): """ This method restores a model from its JSON rep. """ self.module = jrep["module"] self.exec_key = jrep["exec_key"] self.period = jrep["period"] self.switches = jrep["switches"] # We should restore user from json: # self.user = jrep["user"] # But for the moment we will hard code this: self.user = APIUser(model=self, name="API", exec_key=self.exec_key, serial_obj=jrep["user"]) self.user_type = jrep["user_type"] self.props = jrep["props"] self.env = Env(self.module, serial_obj=jrep["env"], exec_key=self.exec_key) # since self.groups is a list and self.env.members is an OrderedDict self.groups = [ self.env.members[group_nm] for group_nm in self.env.members ] def to_json(self): """ This method generates the JSON representation for this model. """ jrep = {} jrep["module"] = self.module jrep["exec_key"] = self.exec_key jrep["period"] = self.period jrep["switches"] = self.switches jrep["user"] = self.user.to_json() jrep["user_type"] = self.user_type jrep["props"] = self.props jrep["env"] = self.env.to_json() jrep["type"] = "Model" return jrep def __str__(self): return self.module def __repr__(self): return json.dumps(self.to_json(), cls=AgentEncoder, indent=4) def create_user(self): """ This will create a user of the correct type. """ self.user = None self.user_type = os.getenv("user_type", API) try: if self.user_type == TERMINAL: self.user = TermUser(model=self, exec_key=self.exec_key) self.user.tell("Welcome to Indra, " + str(self.user) + "!") elif self.user_type == TEST: self.user = TestUser(model=self, exec_key=self.exec_key) else: # right now API is the only other possibility self.user = APIUser(model=self, name="API", exec_key=self.exec_key) return self.user except ValueError: raise ValueError("User type was not specified.") def create_env(self, env_action=None, random_placing=True): """ Override this method to create a unique env... but this one will already set the model name and add the groups. """ # NOTE: WE DEFAULT TO RANDOM PLACING ALL THE TIME # EVEN FOR MODELS LIKE FOREST FIRE self.env = Env(self.module, members=self.groups, exec_key=self.exec_key, width=self.width, height=self.height, action=env_action, random_placing=random_placing) self.env.user = self.user self.env.user_type = self.user_type self.create_pop_hist() return self.env def create_pop_hist(self): self.env.create_pop_hist() def create_groups(self): """ Override this method in your model to create all of your groups. In general, you shouldn't need to: fill in the grp_struct instead. """ self.groups = [] grps = self.grp_struct for grp_nm in grps: grp = grps[grp_nm] num_mbrs = grp_val(grp, NUM_MBRS) if NUM_MBRS_PROP in grp: num_mbrs = self.props.get(grp[NUM_MBRS_PROP], num_mbrs) self.groups.append( Group(grp_nm, action=grp_val(grp, GRP_ACTION), color=grp_val(grp, COLOR), num_mbrs=num_mbrs, mbr_creator=grp_val(grp, MBR_CREATOR), mbr_action=grp_val(grp, MBR_ACTION), exec_key=self.exec_key)) return self.groups def run(self, periods=None): """ This method runs the model. If `periods` is not None, it will run it for that many periods. Otherwise, on a terminal, it will display the menu. Return: 0 if run was fine. """ if (self.user is None) or (self.user_type == TEST) or (self.user_type == API): self.runN() else: self.user.tell("Running model " + self.module) while True: # run until user exit! if self.user() == USER_EXIT: break return 0 def runN(self, periods=DEF_TIME): """ Run our model for N periods. Return the total number of actions taken. """ num_acts = 0 num_moves = 0 for i in range(periods): self.period += 1 # now we call upon the env to act: if DEBUG.debug_lib: print("From model, calling env to act.") (num_acts, num_moves) = self.env() census_rpt = self.rpt_census(num_acts, num_moves) if DEBUG.debug_lib: print(census_rpt) self.user.tell(census_rpt) # these things need to be done before action loop: self.handle_switches() self.update_pop_hist() self.handle_womb() return num_acts def handle_womb(self): """ This method adds new agents from the womb. """ self.env.handle_womb() def add_child(self, group): """ Put a child agent in the womb. group: which group will add new agent """ self.env.add_child(group) def update_pop_hist(self): """ This method records our populations each period. """ self.env.handle_pop_hist() def rpt_census(self, acts, moves): """ This is the default census report. Right now, `acts` is not used: do we need it? Return: a string saying what happened in a period. """ ret = self.env.get_census(moves, self.num_switches) self.num_switches = 0 return ret def pending_switches(self): """ How many switches are there to execute? """ return len(self.switches) def rpt_switches(self): """ Generate a string to report our switches. """ return "# switches = " + str(self.pending_switches()) + "; id: " \ + str(id(self.switches)) def add_switch(self, agent_nm, from_grp_nm, to_grp_nm): """ Switch agent from 1 group to another. The agent and groups should be passed by name. """ self.switches.append((agent_nm, from_grp_nm, to_grp_nm)) def handle_switches(self): """ This will actually process the pending switches. """ if self.switches is not None: for (agent_nm, from_grp_nm, to_grp_nm) in self.switches: switch(agent_nm, from_grp_nm, to_grp_nm, self.exec_key) self.num_switches += 1 self.switches.clear() pass def line_graph(self): self.env.line_graph() def bar_graph(self): self.env.bar_graph() def scatter_plot(self): self.env.scatter_plot()
def main(self): Env.setFromFile('config/env.json') r = Route() return r.main()
def setUp(self): self.exec_key = get_exec_key() self.env = Env("Test env", exec_key=self.exec_key) self.user = TermUser("User", exec_key=self.exec_key) self.test_user = TestUser("TestUser", exec_key=self.exec_key)