def test_same_recipe(self, tmpdir): exp = Experiment(directory=tmpdir, state_class=EmptyState) exp_args = {"a": 10.0, "B": "notused"} root = exp.spawn_new_tree(**exp_args) op = OpRecipe(mul, 0.4, stochastic=False) new_state_a = op(root) new_state_b = op(root) new_state_c = op(root) # make sure this creates three new dask delayed states assert len(exp.leaves) == 3 for leafID, leaf in exp.leaves.items(): assert type(leaf) == Delayed # Since this is the same op on the root, these three ops would result # in 3 identical states. Check, therefore, that only one state is # created exp.run() exp = Experiment.restore(directory=tmpdir, state_class=EmptyState) assert len(exp.graph.node_map) == 2 # root + new state # Test actual restoring from cache by hand by replicating what # happens in `run_recipe` exp1 = Experiment(directory=tmpdir, state_class=EmptyState) root1 = exp1.spawn_new_tree(**exp_args) assert root1.get().from_cache # same root new_state1 = root1.get().new_state(op) assert new_state1.restore()
def test_cache_works(self, tmpdir): exp = Experiment(directory=tmpdir, state_class=EmptyState) exp_args = {"a": 10.0, "B": "notused"} root = exp.spawn_new_tree(**exp_args) # In the stochastic version of this, the output of the Op will change # if `run` is called again. To make sure we're using the cached nodes, # we check to make sure multiple runs yield the same output. op = OpRecipe(mul, 0.4, stochastic=True) result = op(root) out = result.get() assert out.restore() value = out.c # Get the value a second time by re-running through the graph, assert # the same result2 = op(root) out2 = result2.get() assert out2.restore() assert value == out2.c # Remove all cached states, rebuild the experiment, and assert the # value changes. for f in glob.glob(str(tmpdir / "*")): os.remove(f) # Now recreate exp = Experiment(directory=tmpdir, state_class=EmptyState) exp_args = {"a": 10.0, "B": "notused"} root = exp.spawn_new_tree(**exp_args) result3 = op(root) out3 = result3.get() assert out3.restore() assert value != out3.c
def test_bad_recipe(self, tmpdir): # This should fail because run does not return a state! class Bad(Recipe): def run(self, s): return None exp = Experiment(directory=tmpdir, state_class=EmptyState) exp_args = {"a": 10.0, "B": "notused"} root = exp.spawn_new_tree(**exp_args) with pytest.raises(RuntimeError): Bad()(root).get()
def test_function_exception(self, tmpdir): """Test that when the function fails, the relative error gets raised upon running the graph (not at graph definition time). """ exp = Experiment(directory=tmpdir, state_class=EmptyState) exp_args = {"a": 1, "B": 2} root = exp.spawn_new_tree(**exp_args) function = Function(lambda s: print("d = {}".format(s.d))) s = function(root) with pytest.raises(AttributeError): exp.run()
def test_spawn_new_tree(self, tmpdir): """ """ exp = Experiment(directory=tmpdir, state_class=EmptyState) # The argument 'c' should be ignored, as it is not set from thew # constructor in spawn_new_tree exp_args = {"a": "first", "B": "second", "c": "shouldnotpropagate"} root = exp.spawn_new_tree(**exp_args) assert type(root) == ExperimentStatePromise root_state = root.get() assert exp.root is root_state assert isinstance(root_state, EmptyState) assert root_state.a == exp_args["a"] assert root_state.B == exp_args["B"] assert root_state.c is None
def test_function_safe_op(self, tmpdir): """Regardless of whether the op in the function fails or succeeds, the state it acts on gets deflated. """ exp = Experiment(directory=tmpdir, state_class=EmptyState) exp_args = {"a": 1, "B": 2} root = exp.spawn_new_tree(**exp_args) exp.run() exp = Experiment.restore(directory=tmpdir, state_class=EmptyState) assert exp.root.slim_loaded badfunction = Function(lambda s: print("d = {}".format(s.d))) with pytest.raises(AttributeError): s = badfunction._safe_op(exp.root) assert exp.root.slim_loaded goodfunction = Function(lambda s: print("a = {}".format(s.a))) s = goodfunction._safe_op(exp.root) assert exp.root.slim_loaded
def test_function(self, tmpdir): exp = Experiment(directory=tmpdir, state_class=EmptyState) exp_args = {"a": 1, "B": 2} root = exp.spawn_new_tree(**exp_args) op = OpRecipe(mul, 0.4) state1 = op(root) assert len(exp.leaves) == 1 leaf1 = list(exp.leaves.items())[0] function = Function(lambda s: print("c = {}".format(s.c))) state2 = function(state1) # The state should not be modified by the function because functions # are non state mutating operations assert state2 == state1 # check that the previous leaf has been replaced by the new leaf assert len(exp.leaves) == 1 leaf2 = list(exp.leaves.items())[0] assert leaf2 != leaf1
def test_spawn_new_tree_recipe(self, tmpdir): exp = Experiment(directory=tmpdir, state_class=EmptyState) exp_args = {"a": 10.0, "B": "notused"} root = exp.spawn_new_tree(**exp_args) # This recipe sets the non-hashed attribute `c`, so we check that we # do state.c = 10 * 1.5 op = OpRecipe(mul, 1.5) result = op(root) out = result.get() # When we `get` the result, it will be slim-loaded, verify that and # restore the output. assert out.slim_loaded assert out.restore() assert not out.slim_loaded # Very the Op was applied assert out.c == 15.0
def test_tag_filtering(self, tmpdir): exp = Experiment(directory=tmpdir, state_class=EmptyState) exp_args = {"a": 1.0, "B": 2.0, "c": 3.0} root = exp.spawn_new_tree(**exp_args) op_add = OpRecipe(add, 1.2) with exp.tag("ops"): with exp.tag("phase:mul"): x1 = OpRecipe(mul, 0.4)(root) x2 = OpRecipe(mul, 0.5)(root) with exp.tag("phase:add"): y1 = op_add(x1) y2 = op_add(x2) exp.run() exp = Experiment.restore(directory=tmpdir, state_class=EmptyState) assert len(exp.graph.nodes.filter("op*")) == 4 assert ( len( exp.graph.nodes.filter("phase:mul") | exp.graph.nodes.filter("phase:add") ) == 4 ) assert len(exp.graph.nodes.filter("!phase:mul")) == 3 assert ( len( exp.graph.nodes.filter("ops") & exp.graph.nodes.filter("!phase:add") ) == 2 ) # Cannot compose other objects with a nodeset with pytest.raises(TypeError): exp.graph.nodes.filter("phase:mul") | "hi" with pytest.raises(TypeError): exp.graph.nodes.filter("phase:*") & "!hi"
def test_spawn_new_tree_error(self, tmpdir): exp = Experiment(directory=tmpdir, state_class=EmptyState) exp_args = {} with pytest.raises(KeyError): exp.spawn_new_tree(**exp_args)