def setUp(self): self.x = Monomer.from_string("x0 x1", "X") self.y = Monomer.from_string("2(y0) 1(y1) 3(y2)", "Y") self.polymer_1x = Polymer({self.x: 1}) self.polymer_1y = Polymer({self.y: 1}) self.polymer_1x_1y = Polymer({self.y: 1, self.x: 1}) self.polymer_2x_3y = Polymer({self.y: 3, self.x: 2})
def test_energy(self): # values determined by regression testing monomer_a = Monomer.from_string("a a b b c d") monomer_b = Monomer.from_string("a* b* c*") polymer_a = Polymer({monomer_a: 1}) polymer_b = Polymer({monomer_b: 1}) polymer_ab = Polymer({monomer_a: 1, monomer_b: 1}) polymer_aab = Polymer({monomer_a: 2, monomer_b: 1}) polymer_abb = Polymer({monomer_a: 1, monomer_b: 2}) self.assertEqual(0.0, Configuration({}).energy(bond_weighting_factor=0.4)) self.assertEqual( 1.0, Configuration({ polymer_a: 1, polymer_ab: 1 }).energy(bond_weighting_factor=0.4)) self.assertEqual( 2.2, Configuration({ polymer_a: infinity, polymer_b: 1, polymer_ab: 1 }).energy(bond_weighting_factor=0.4)) self.assertEqual( 1.8, Configuration({ polymer_b: infinity, polymer_ab: 1 }).energy(bond_weighting_factor=0.4)) self.assertEqual( 4.8, Configuration({ polymer_b: infinity, polymer_aab: 1 }).energy(bond_weighting_factor=0.4)) self.assertEqual( 2.4, Configuration({ polymer_a: infinity, polymer_abb: 1 }).energy(bond_weighting_factor=0.4)) # case to test a fix to a bug in a specific example in which energy was misreported as 0.8 (should be 1.6) # two limiting monomers with two domains each, all as singletons => 0.4(4 domains) = 1.6 monomer_x = Monomer.from_string("a b") monomer_y = Monomer.from_string("a* b*") polymer_x = Polymer({monomer_x: 1}) polymer_y = Polymer({monomer_y: 1}) self.assertEqual( 1.6, Configuration({ polymer_x: 2, polymer_y: infinity }).energy(bond_weighting_factor=0.4))
def setUp(self): self.x = Monomer.from_string("x0 x1", "X") self.y = Monomer.from_string("2(y0) 1(y1) 3(y2)", "Y") self.Tbn_1x = Tbn({self.x: 1}) self.Tbn_1y = Tbn({self.y: 1}) self.Tbn_1x_1y = Tbn({self.y: 1, self.x: 1}) self.Tbn_2x_3y = Tbn({self.y: 3, self.x: 2}) self.Tbn_infx_2y = Tbn({self.x: infinity, self.y: 2}) self.Tbn_2x_infy = Tbn({self.y: infinity, self.x: 2}) self.Tbn_1x_infy = Tbn({self.y: infinity, self.x: 1})
def test_limiting_monomer_types(self): test_tbn = Tbn({ Monomer.from_string("a b c e"): infinity, Monomer.from_string("a d*"): 1, Monomer.from_string("d*"): infinity, Monomer.from_string("a*"): 2, # a* is limiting in this example Monomer.from_string("a d e*"): 3, # both d and e* are limiting in this example Monomer.from_string("f"): 1, Monomer.from_string("f*"): 1, # f* is chosen as limiting to break the tie (favors stars) }) limiting_monomer_types = sorted([ Monomer.from_string("a d e*"), Monomer.from_string("a*"), Monomer.from_string("f*") ]) self.assertEqual(limiting_monomer_types, list(test_tbn.limiting_monomer_types()))
def from_string(cls, text) -> "Tbn": monomer_counts = {} for raw_line in text.split('\n'): line = raw_line.strip() if line: # not just whitespace quantity_search_result = re.match( f"^(|inf|[1-9]\\d*)\\[\\s*({Monomer.regex()})\\s*\\]$", line ) if quantity_search_result: raw_count, monomer_string = quantity_search_result.groups() if raw_count == "inf": count = infinity elif raw_count == "": count = 1 else: count = int(raw_count) else: count = 1 monomer_string = line monomer = Monomer.from_string(monomer_string) monomer_counts[monomer] = monomer_counts.get(monomer, 0) + count return Tbn(monomer_counts)
def test_from_string(self): with self.subTest("single monomer example"): self.assertEqual(Tbn({Monomer.from_string("a"): 1}), Tbn.from_string("a")) with self.subTest("single monomer type, multiple monomer example"): self.assertEqual(Tbn({Monomer.from_string("a"): 2}), Tbn.from_string("2[a]")) with self.subTest("testing from_string with example from stablegen.net/help"): example_text = \ """ a*:b1 b* a b:b2 >m1 a* >m2 b* """ example_tbn = Tbn({ Monomer.from_string("a* b*"): 1, Monomer.from_string("a b", "m1"): 1, Monomer.from_string("a*", "m2"): 1, Monomer.from_string("b*"): 1, }) self.assertEqual(example_tbn, Tbn.from_string(example_text)) with self.subTest("testing from_string with multisets"): multiset_text = \ """ 2[ 3(a*) a b ] [ c ] 5[ a a:favorite_a b >bob ] 7[ b a b b ] b a b b b* """ multiset_tbn = Tbn({ Monomer.from_string("a* a* a* a b"): 2, Monomer.from_string("c"): 1, Monomer.from_string("2(a) b", "bob"): 5, Monomer.from_string("3(b) a"): 7, Monomer.from_string("b* 3(b) a"): 1, }) self.assertEqual(multiset_tbn, Tbn.from_string(multiset_text)) with self.subTest("testing from_string with excess monomers"): multiset_text = \ """ 2[ 3(a*) a b ] inf[ c ] 5[ a a b >bob ] inf[ b a b b ] b a b b b* """ multiset_tbn = Tbn({ Monomer.from_string("a* a* a* a b"): 2, Monomer.from_string("c"): infinity, Monomer.from_string("2(a) b", "bob"): 5, Monomer.from_string("3(b) a"): infinity, Monomer.from_string("b* 3(b) a"): 1, }) self.assertEqual(multiset_tbn, Tbn.from_string(multiset_text))
def test_eq(self): self.assertEqual(Tbn({Monomer.from_string("a"): 1}), Tbn({Monomer.from_string("a"): 1})) self.assertEqual(Tbn({Monomer.from_string("a"): infinity}), Tbn({Monomer.from_string("a"): infinity})) self.assertNotEqual(Tbn({Monomer.from_string("a"): 1}), Tbn({Monomer.from_string("a"): 2})) self.assertNotEqual(Tbn({Monomer.from_string("a"): 1}), Tbn({Monomer.from_string("b"): 1})) self.assertNotEqual(Tbn({Monomer.from_string("a"): 1}), Tbn({Monomer.from_string("a"): infinity}))
def test_limiting_domain_types(self): tests = [ ({}, []), ({self.x: 3}, [Domain("x0*"), Domain("x1*")]), ({self.y: 5}, [Domain("y0*"), Domain("y1*"), Domain("y2*")]), ({self.x: 5, self.y: 2}, [Domain("x0*"), Domain("x1*"), Domain("y0*"), Domain("y1*"), Domain("y2*")]), ({Monomer.from_string("a*"): 2, Monomer.from_string("a"): 1}, [Domain("a")]), ({Monomer.from_string("3(a*)"): 1, Monomer.from_string("a"): 2}, [Domain("a")]), ({Monomer.from_string("a*"): 1, Monomer.from_string("a"): 2}, [Domain("a*")]), ({Monomer.from_string("2(a*)"): 1, Monomer.from_string("a"): 2}, [Domain("a*")]), ({Monomer.from_string("2(a*)"): 1, Monomer.from_string("a"): infinity}, [Domain("a*")]), ({Monomer.from_string("2(a*)"): infinity, Monomer.from_string("a"): 2}, [Domain("a")]), ] for monomer_multiset, expected_limiting_domain_types in tests: with self.subTest("limiting domain types", tbn=str(Tbn(monomer_multiset))): limiting_domain_types = list(Tbn(monomer_multiset).limiting_domain_types()) self.assertEqual(expected_limiting_domain_types, limiting_domain_types) with self.subTest("cannot have conflicting excess domain types"): conflicting_excess_tbn = Tbn( {Monomer.from_string("a"): infinity, Monomer.from_string("a*"): infinity} ) with self.assertRaises(AssertionError): list(conflicting_excess_tbn.limiting_domain_types()) with self.subTest("test equal count tie-breaking filter"): monomer_multiset = { Monomer.from_string("2(a)"): 1, Monomer.from_string("a*"): 2, Monomer.from_string("b*"): 1 } limiting_domain_types = list(Tbn(monomer_multiset).limiting_domain_types(filter_ties=True)) self.assertEqual([Domain("b")], limiting_domain_types)
def setUp(self): self.x = Monomer.from_string("x0 x1 >X") self.y = Monomer.from_string("2(y0) 1(y1) 3(y2) >Y") self.abc_star = Monomer.from_string("a b c*") self.triple_a_star = Monomer.from_string("a* a* a*") self.semi_self_saturated_monomer = Monomer.from_string("a a* b b b*")
def test_eq(self): with self.subTest("equal to self"): self.assertEqual(self.x, self.x) self.assertEqual(self.y, self.y) self.assertEqual(self.abc_star, self.abc_star) self.assertEqual(self.triple_a_star, self.triple_a_star) self.assertEqual(self.semi_self_saturated_monomer, self.semi_self_saturated_monomer) with self.subTest("equal to equivalent monomer"): self.assertEqual(self.x, Monomer.from_string("x0 x1 >X")) self.assertEqual(self.y, Monomer.from_string("2(y0) 1(y1) 3(y2) >Y")) self.assertEqual(self.abc_star, Monomer.from_string("a b c*")) self.assertEqual(self.triple_a_star, Monomer.from_string("a* a* a*")) self.assertEqual(self.triple_a_star, Monomer.from_string("3(a*)")) self.assertEqual(self.semi_self_saturated_monomer, Monomer.from_string("a a* b b b*")) with self.subTest("equal to equivalent monomer with order switched"): self.assertEqual(self.x, Monomer.from_string("x1 x0 >X")) self.assertEqual(self.abc_star, Monomer.from_string("c* a b")) self.assertEqual(self.y, Monomer.from_string("y1 2(y0) 3(y2) >Y")) self.assertEqual(self.semi_self_saturated_monomer, Monomer.from_string("a b a* b b*")) with self.subTest("not equal to monomer with different name"): self.assertNotEqual(self.x, Monomer.from_string("z0 z1 >Z_test1")) self.assertNotEqual(self.x, Monomer.from_string("x0 x1 >Z_test2")) self.assertNotEqual( self.y, Monomer.from_string("2(y0) 1(y1) 3(y2) >Z_test3")) self.assertNotEqual(self.triple_a_star, Monomer.from_string("a* a* a* >Z_test4"))
def test_init(self): for quantity in [0, -1, -2, 'a', '^', float("inf")]: with self.subTest( "Do not allow nonpositive or infinite domain quantities", quantity=quantity): with self.assertRaises(AssertionError): Monomer({ Domain("xx"): 2, Domain("yy"): quantity }, "bad_monomer") with self.subTest("Do not allow empty monomers"): with self.assertRaises(AssertionError): Monomer.from_string("") with self.assertRaises(AssertionError): Monomer.from_string(">empty_monomer") for name in ["X", "Y"]: with self.subTest("No duplicate names", name=name): with self.assertRaises(AssertionError): Monomer.from_string(f"z0 z1 >{name}") with self.subTest("Accept duplicate monomer name if domains match"): Monomer.from_string("x0 x1 >X") Monomer.from_string("2(y0) 1(y1) 3(y2) >Y") Monomer.from_string("2(y0) y1 3(y2) >Y") with self.subTest( "Accept duplicate monomer name if domains match but are switched" ): Monomer.from_string("x1 x0 >X") Monomer.from_string("1(y1) 2(y0) 3(y2) >Y") Monomer.from_string("y1 2(y0) 3(y2) >Y") Monomer.from_string("c* a b") Monomer.from_string("a b a* b b*") with self.subTest( "Do not collapse complements; e.g. do not annihilate a with a*" ): Monomer.from_string("b") Monomer.from_string("a a* b")