def test_parse_crn_string(self): crn = "A+B->X+Y\nA<=>X" res = ([[['A', 'B'], ['X', 'Y'], [None]], [['A'], ['X'], [None, None]]], ['A', 'B', 'X', 'Y'], ['A', 'B', 'X', 'Y'], []) self.assertEqual(parse_crn_string(crn), res, 'chemical reaction network 1') crn = "A+B->X+Y;A<=>X;formals={A,B,X};signals={Y}" res = ([[['A', 'B'], ['X', 'Y'], [None]], [['A'], ['X'], [None, None]]], ['A', 'B', 'X', 'Y'], ['Y'], []) self.assertEqual(parse_crn_string(crn), res, 'chemical reaction network 2')
def test_parse_reaction_string(self): """ Testing crn string parser """ crn = "A+B->X+Y" res = ([[['A', 'B'], ['X', 'Y'], [None]]], ['A', 'B', 'X', 'Y'], ['A', 'B', 'X', 'Y'], []) self.assertEqual(parse_crn_string(crn), res, 'single chemical reaction 1') crn = "A<=>B" res = ([[['A'], ['B'], [None,None]]], ['A', 'B'], ['A', 'B'], []) self.assertEqual(parse_crn_string(crn), res, 'single chemical reaction 2') crn = "->X" res = ([[[], ['X'], [None]]], ['X'], ['X'], []) self.assertEqual(parse_crn_string(crn), res, 'single chemical reaction 3') crn = "B->" res = ([[['B'], [], [None]]], ['B'], ['B'], []) self.assertEqual(parse_crn_string(crn), res, 'single chemical reaction 4')
def translate(input_crn, ts_file, pilfile=None, dnafile=None, verbose=False): """CRN-to-DSD translation wrapper function. A formal chemical reaction network (CRN) is translated into a domain-level strand displacement (DSD) system. The translation-scheme and the CRN are parsed into low-level instructions using the **nuskell.parser** module, passed on to the **nuskell.interpreter** and returned in form of a **nuskell.objects.TestTube()** object. Args: input_crn (str): An input string representation of the formal CRN. ts_file (str): The input file name of a translation scheme. pilfile (str, optional): Prints the DSD system in form of a PIL file. Defaults to None. dnafile (str, optional): Prints the DSD system in form of a VisualDSD DNA file. Defaults to None. verbose (bool, optional): Print logging information during translation. Defaults to False. Returns: [:obj:`TestTube()`,...]: A list of TestTube objects. The first object contains signal and fuel species of the full DSD system, followed by *experimental* modular system specifications. """ TestTube.warnings = verbose if not os.path.isfile(ts_file): builtin = 'schemes/' + ts_file try: ts_file = pkg_resources.resource_filename('nuskell', builtin) print "Using scheme:", ts_file except KeyError: schemedir = pkg_resources.resource_filename('nuskell', 'schemes') raise InvalidSchemeError(ts_file, schemedir) ts = parse_ts_file(ts_file) crn, fs, signals, fuels = parse_crn_string(input_crn) solution, constant_solution = interpret(ts, crn, fs) if pilfile: with open(pilfile, 'w') as pil: TestTubeIO(solution).write_pil_kernel(pil) if dnafile: with open(dnafile, 'w') as dna: TestTubeIO(solution).write_dnafile(dna, signals=fs, crn=crn, ts=os.path.basename(ts_file)) return solution, constant_solution
def test_example_02(self): # """A simple example of finding a bisimulation from group meeting.""" fcrn = "A + B -> C + D ; A + C -> B + D" icrn = "x1 -> x2 ; x3 + x4 <=> x5 ; x2 -> x6 + x8 ; x5 -> x7 ; " + \ "x3 <=> x6 ; x9 <=> x10 ; x10 + x4 <=> x1 ; x7 -> x9 + x8" (fcrn, fs, _) = parse_crn_string(fcrn) fcrn = split_reversible_reactions(fcrn) fcrn = [[Counter(part) for part in rxn] for rxn in fcrn] (icrn, _, _) = parse_crn_string(icrn) icrn = split_reversible_reactions(icrn) icrn = [[Counter(part) for part in rxn] for rxn in icrn] v, _ = bisimulation.test(fcrn, icrn, fs) self.assertTrue(v) # Test wrong partial interpretation partial = dict() partial['x2'] = Counter(['B', 'D']) partial['x3'] = Counter(['C']) v, i = bisimulation.test(fcrn, icrn, fs, interpretation=partial, permissive='loop-search', verbose=False) self.assertFalse(v) del partial['x3'] v, _ = bisimulation.test(fcrn, icrn, fs, permissive='loop-search', interpretation=partial, verbose=False) self.assertTrue(v)
def test_parse_crn_string_oneline(self): crn = "A+C->X+Y; Y<=>L; L -> C+A" out = ([[['A', 'C'], ['X', 'Y'], [None]], [['Y'], ['L'], [None, None]], [['L'], ['C', 'A'], [None]] ], ['A', 'C', 'L', 'X', 'Y'], ['A', 'C', 'L', 'X', 'Y'], []) self.assertEqual(parse_crn_string(crn), out, 'oneline CRN format') crn = "A+C->X+Y; formals={A1, A2, B2}" out = ([[['A', 'C'], ['X', 'Y'], [None]]], ['A', 'A1', 'A2', 'B2', 'C','X','Y'], ['A', 'A1', 'A2', 'B2', 'C','X','Y'], []) self.assertEqual(parse_crn_string(crn), out, 'oneline CRN format') crn = "A+C->X+X; formals={A1, A2, B2}" out = ([[['A', 'C'], ['X', 'X'], [None]]], ['A', 'A1', 'A2', 'B2', 'C','X'], ['A', 'A1', 'A2', 'B2', 'C','X'], []) self.assertEqual(parse_crn_string(crn), out, 'oneline CRN format') crn = "A+C->2X; formals={A1, A2, B2}" out = ([[['A', 'C'], ['X', 'X'], [None]]], ['A', 'A1', 'A2', 'B2', 'C','X'], ['A', 'A1', 'A2', 'B2', 'C','X'], []) self.assertEqual(parse_crn_string(crn), out, 'oneline CRN format') crn = "A+C->X+Y; formals={A1, A2, B2, X, Y}; fuels={}" out = ([[['A', 'C'], ['X', 'Y'], [None]]], ['A', 'A1', 'A2', 'B2', 'C', 'X', 'Y'], ['A', 'A1', 'A2', 'B2', 'C', 'X', 'Y'], []) self.assertEqual(parse_crn_string(crn), out, 'oneline CRN format') crn = "A+C->X+Y; Y<=>L; L->C+A; formals={A, x, y}; signals={L, C}" out = ([ [['A', 'C'], ['X', 'Y'], [None]], [['Y'], ['L'], [None, None]], [['L'], ['C', 'A'], [None]] ], ['A', 'C', 'L', 'X', 'Y', 'x', 'y'], ['C', 'L'], []) self.assertEqual(parse_crn_string(crn), out, 'oneline CRN format')
def _parse_crn_string(self, string): crn, formal, _, _ = parse_crn_string(string) crn = split_reversible_reactions(crn) return ([[Counter(part) for part in rxn] for rxn in crn], formal)
def test_example_03(self): #""" a follow-up on testing the groupmeeting example """ fcrn = "A + B -> C + D ; A + C -> B + D" icrn = "x1 -> x2 ; x3 + x4 <=> x5 ; x2 -> x6 + x8 ; x5 -> x7 ; " + \ "x3 <=> x6 ; x9 <=> x10 ; x10 + x4 <=> x1 ; x7 -> x9 + x8" # First correct interpretation inter1 = { 'x1': Counter({ 'A': 1, 'B': 1 }), 'x2': Counter({ 'C': 1, 'D': 1 }), 'x3': Counter({'C': 1}), 'x4': Counter({'A': 1}), 'x5': Counter({ 'A': 1, 'C': 1 }), 'x6': Counter({'C': 1}), 'x7': Counter({ 'B': 1, 'D': 1 }), 'x8': Counter({'D': 1}), 'x9': Counter({'B': 1}), 'x10': Counter({'B': 1}) } pinter1 = {'x7': Counter({'B': 1, 'D': 1})} # Second correct interpretation inter2 = { 'x1': Counter({ 'A': 1, 'C': 1 }), 'x2': Counter({ 'B': 1, 'D': 1 }), 'x3': Counter({'B': 1}), 'x4': Counter({'A': 1}), 'x5': Counter({ 'A': 1, 'B': 1 }), 'x6': Counter({'B': 1}), 'x7': Counter({ 'C': 1, 'D': 1 }), 'x8': Counter({'D': 1}), 'x9': Counter({'C': 1}), 'x10': Counter({'C': 1}) } pinter2 = {'x7': Counter({'C': 1, 'D': 1})} # CRN preprocessing (fcrn, fs, _) = parse_crn_string(fcrn) fcrn = split_reversible_reactions(fcrn) fcrn = [[Counter(part) for part in rxn] for rxn in fcrn] (icrn, _, _) = parse_crn_string(icrn) icrn = split_reversible_reactions(icrn) icrn = [[Counter(part) for part in rxn] for rxn in icrn] # NOTE: Correct behavior v, i1 = bisimulation.test(fcrn, icrn, fs, interpretation=pinter1, permissive='whole-graph') self.assertTrue(v) self.assertDictEqual(inter1, i1) v, i1 = bisimulation.test(fcrn, icrn, fs, interpretation=pinter1, permissive='loop-search') self.assertTrue(v) self.assertDictEqual(inter1, i1) v, i1 = bisimulation.test(fcrn, icrn, fs, interpretation=pinter1, permissive='depth-first') self.assertTrue(v) self.assertDictEqual(inter1, i1) v, i1 = bisimulation.test(fcrn, icrn, fs, interpretation=inter1, permissive='loop-search') self.assertTrue(v) self.assertDictEqual(inter1, i1) v, i1 = bisimulation.test(fcrn, icrn, fs, interpretation=inter1, permissive='whole-graph') self.assertTrue(v) self.assertDictEqual(inter1, i1) v, i1 = bisimulation.test(fcrn, icrn, fs, interpretation=inter1, permissive='depth-first') self.assertTrue(v) self.assertDictEqual(inter1, i1) v, i2 = bisimulation.test(fcrn, icrn, fs, interpretation=pinter2, permissive='loop-search') self.assertTrue(v) self.assertDictEqual(inter2, i2) v, i2 = bisimulation.test(fcrn, icrn, fs, interpretation=pinter2, permissive='whole-graph') self.assertTrue(v) self.assertDictEqual(inter2, i2) v, i2 = bisimulation.test(fcrn, icrn, fs, interpretation=pinter2, permissive='depth-first') self.assertTrue(v) self.assertDictEqual(inter2, i2)
def test_split_reversible_reactions(self): crn = "A+B->X+Y\nA<=>X" crn, fs, signals, fuels = parse_crn_string(crn) res = [[['A', 'B'], ['X', 'Y'], [None]], [['A'], ['X'], [None]], [['X'], ['A'],[None]]] self.assertEqual(split_reversible_reactions(crn), res, 'split irreversible reactions')
def main(): """ CRN condensation. Takes a formal and an implementation CRN and verifies the equivalence according to pathway decomposition or bisimulation. Throws out edges from the graph to see how equivalence notion changes. """ parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser = get_nuskell_args(parser) args = parser.parse_args() # ~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Parse and process input CRN # ~~~~~~~~~~~~~~~~~~~~~~~~~~~ input_crn = sys.stdin.readlines() input_crn = "".join(input_crn) crn1, crn1s, _, _ = parse_crn_string(input_crn) # ~~~~~~~~~~~~~~~~~~~~~~~~~~ # Verify equivalence of CRNs # ~~~~~~~~~~~~~~~~~~~~~~~~~~ print "\nVerification preprocessing..." crn1 = split_reversible_reactions(crn1) if args.verbose: print "Formal CRN:" printCRN(crn1, reversible=True, rates=False) crn2, crn2s, _, _ = parse_crn_file(args.compare) crn2 = split_reversible_reactions(crn2) if args.verbose: print "Implementation CRN:" printCRN(crn2, reversible=True, rates=False) interpret = dict() if not args.independent: print 'Ad-hoc partial interpretation:' formals = set(crn1s) for sp in crn2s: if sp in formals: interpret[sp] = Counter([sp]) if interpret and args.verbose: for impl, formal in sorted(interpret.items()): print " {} => {}".format( impl, ', '.join([x for x in formal.elements()])) print "\nVerification using:", args.verify for meth in args.verify: v, i = verify(crn1, crn2, crn1s, method=meth, interpret=interpret, verbose=(args.verbose > 1), timeout=args.verify_timeout) if i and args.verbose: if not v: i = i[0] print "Returned interpretation ['{}']:".format(meth) for impl, formal in sorted(i.items()): print " {} => {}".format( impl, ', '.join([x for x in formal.elements()])) if v is True: print " {}: CRNs are {} equivalent.".format(v, meth) elif v is False: print " {}: CRNs are not {} equivalent.".format(v, meth) elif v is None: print " {}: {} verification did not terminate within {} seconds.".format( v, meth, args.verify_timeout)
def _parse_crn_string(self, string): crn, formal, _, _ = parse_crn_string(string) crn = split_reversible_reactions(crn) return (crn, formal)