def test_copy_same_values(self): """ Basic test: the copy should have similarly valued attribute values as the original. """ pos = torch.tensor([1.], dtype=torch.float) vel = torch.tensor([2.], dtype=torch.float) acc = torch.tensor([3.], dtype=torch.float) mass = 4 attraction_funct = ATTRACT_FUNCT stiffnesses = generate_stiffness_dict(0.5, 0.6, 0.7, 0.8) original = Node(pos, vel, acc, mass, attraction_funct, **stiffnesses) copy = original.copy() self.assertFalse(copy is original) self.assertTrue(torch.allclose(acc, copy.acc)) self.assertTrue(torch.allclose(vel, copy.vel)) self.assertTrue(torch.allclose(pos, copy.pos)) self.assertEqual(mass, copy.mass) self.assertTrue(attraction_funct is copy._attraction_function) self.assertAlmostEqual(copy.marble_stiffness, stiffnesses["marble_stiffness"]) self.assertAlmostEqual(copy.node_stiffness, stiffnesses["node_stiffness"]) self.assertAlmostEqual(copy.marble_attraction, stiffnesses["marble_attraction"]) self.assertAlmostEqual(copy.node_attraction, stiffnesses["node_attraction"])
def test_spawn_distance(self): """ Should raise error when the distance of the spawned Marble is greater than specified in constants.py """ node_pos = ZERO radius = 1 marble_pos = node_pos + radius + 2 * MAX_EMITTER_SPAWN_DIST other_settings = { "vel": ZERO, "acc": ZERO, "mass": 0, "attraction_function": ATTRACT_FUNCT } other_settings.update(generate_stiffness_dict(0, 0, 0, 0)) prototype_marble = Marble(pos=marble_pos, datum=None, **other_settings) emitter = MockEmitter(prototype_marble, 0) def gen_node(): return MarbleEmitterNode(pos=node_pos, emitter=emitter, radius=radius, **other_settings) self.assertRaises(ValueError, gen_node)
def test_error_if_mass_not_tensor(self): pos = torch.tensor([1.]) vel = torch.tensor([2.]) acc = torch.tensor([3.]) mass = 4 datum = 5 attraction_funct = ATTRACT_FUNCT stiffnesses = generate_stiffness_dict(0.6, 0.7, 0.8, 0.9) with self.assertRaises(ValueError): EmittedMarble(pos, vel, acc, mass, attraction_funct, datum=datum, **stiffnesses)
def test_copy(self): """ Test copying a MarbleEmitterNode. Trainable init_ variables should keep a reference to the original. The emitter should be copied, and *not* be a reference to the original. This is because the stored mass of the new Node may differ over time from the original! """ pos = torch.tensor([1], dtype=torch.float) vel = torch.tensor([2], dtype=torch.float) acc = torch.tensor([3], dtype=torch.float) mass = 4 attraction_funct = ATTRACT_FUNCT stiffnesses = generate_stiffness_dict(0.5, 0.6, 0.7, 0.8) radius = 9 emitter = MockEmitter(MockPrototype(), 0) original = MarbleEmitterNode(pos, vel, acc, mass, attraction_funct, radius=radius, emitter=emitter, **stiffnesses) copy = original.copy() self.assertFalse(copy is original) self.assertTrue(torch.allclose(acc, copy.acc)) self.assertTrue(torch.allclose(vel, copy.vel)) self.assertTrue(torch.allclose(pos, copy.pos)) self.assertEqual(mass, copy.mass) self.assertTrue(attraction_funct is copy._attraction_function) self.assertAlmostEqual(copy.marble_stiffness, stiffnesses["marble_stiffness"]) self.assertAlmostEqual(copy.node_stiffness, stiffnesses["node_stiffness"]) self.assertAlmostEqual(copy.marble_attraction, stiffnesses["marble_attraction"]) self.assertAlmostEqual(copy.node_attraction, stiffnesses["node_attraction"]) self.assertEqual(copy.radius, radius) self.assertEqual(copy.num_marbles_eaten, 0) self.assertIsNot(emitter, copy.emitter)
def create_particle() -> MarbleEmitterNode: pos = torch.tensor([1], dtype=torch.float) vel = torch.tensor([2], dtype=torch.float) acc = torch.tensor([3], dtype=torch.float) mass = 4 attraction_funct = ATTRACT_FUNCT stiffnesses = generate_stiffness_dict(0.5, 0.6, 0.7, 0.8) radius = 9 emitter = MockEmitter(MockPrototype(), 0) output = MarbleEmitterNode(pos, vel, acc, mass, attraction_funct, radius=radius, emitter=emitter, **stiffnesses) return output
def test_parameters(self): pos = torch.tensor([1], dtype=torch.float) vel = torch.tensor([2], dtype=torch.float) acc = torch.tensor([3], dtype=torch.float) mass = 4 attraction_funct = ATTRACT_FUNCT stiffnesses = generate_stiffness_dict(0.5, 0.6, 0.7, 0.8) node = Node(pos, vel, acc, mass, attraction_funct, **stiffnesses) named_params = node.named_parameters() expected_names = { '_Node__marble_stiffness': stiffnesses["marble_stiffness"], '_Node__node_stiffness': stiffnesses["node_stiffness"], '_Node__marble_attraction': stiffnesses["marble_attraction"], '_Node__node_attraction': stiffnesses["node_attraction"] } self.assertTrue( check_named_parameters(expected_names, tuple(named_params)))
def test_no_error_if_mass_is_non_leaf(self): pos = torch.tensor([1.]) vel = torch.tensor([2.]) acc = torch.tensor([3.]) a = torch.tensor([4.], requires_grad=True) mass = 3 * a datum = 5 attraction_funct = ATTRACT_FUNCT stiffnesses = generate_stiffness_dict(0.6, 0.7, 0.8, 0.9) assert not mass.is_leaf, "Testcase broken" try: EmittedMarble(pos, vel, acc, mass, attraction_funct, datum=datum, **stiffnesses) except ValueError as e: self.fail( f"Error raised by __init__, but input is valid. Error: {e}")
from nenwin.marble_eater_node import MarbleEaterNode from nenwin.node import Node, Marble from nenwin.attraction_functions.attraction_functions \ import ThresholdGravity, ConstantAttraction from nenwin.architectures.run_and_visualize import run from nenwin.auxliary import generate_stiffness_dict, generate_node_dict,\ distance from nenwin.output_reader import NumMarblesOutputReader from nenwin.marble_emitter_node import MarbleEmitterNode, MarbleEmitter ZERO = np.array([0, 0]) THRESHOLD = 100 ATTRACTION_FUNCTION = ThresholdGravity(THRESHOLD) ZERO_ATTRACTION = ConstantAttraction(0) NODE_STIFFNESSES = generate_stiffness_dict(marble_stiffness=1, node_stiffness=1, marble_attraction=1, node_attraction=0) EMITTER_STIFFNESSES = generate_stiffness_dict(marble_stiffness=1, node_stiffness=1, marble_attraction=0, node_attraction=0) BIT_MARBLE_STIFFNESS = generate_stiffness_dict(marble_stiffness=1, node_stiffness=0, marble_attraction=1, node_attraction=0) READER_MARBLE_STIFFNESS = generate_stiffness_dict(marble_stiffness=0, node_stiffness=1, marble_attraction=0, node_attraction=0) LOCKER_NODE_MASS = 100000
An experiment to see if an architecture can be made that accelerates a ḿarble in a straight line. """ import numpy as np from typing import List from nenwin.marble_eater_node import MarbleEaterNode from nenwin.node import Node, Marble from nenwin.attraction_functions.attraction_functions import NewtonianGravity from nenwin.architectures.run_and_visualize import run from nenwin.auxliary import generate_stiffness_dict ZERO = np.array([0, 0]) ATTRACTION_FUNCTION = NewtonianGravity() NODE_STIFFNESSES = generate_stiffness_dict(marble_stiffness=1, node_stiffness=1, marble_attraction=1, node_attraction=0) MARBLE_STIFFNESS = generate_stiffness_dict(marble_stiffness=0, node_stiffness=0, marble_attraction=0, node_attraction=0) def cannon_experiment(): """ Simulate a NAND gate using a Nenwin architecture. Also visualizes the simulation and prints the result. """ marble = Marble(pos=np.array([50, 50]), vel=np.array([10, 0]), acc=ZERO,