def printCRN(crn, reversible=True, rates=True): """Pretty printing of CRNs. Args: crn (list of lists): A CRN in list of list format. reversible (bool, optional): True to combine reversible reactions into one line. False to split reversible reactions into irreversible reactions. Note: Order of reactants/products may differ from the order in the crn argument. """ if not rates: pcrn = map(lambda rxn: rxn[:2] + [[None]], crn) else: pcrn = [r for r in crn] if reversible: pcrn = combine_reversible_reactions(pcrn) else: pcrn = split_reversible_reactions(pcrn) for rxn in pcrn: assert len(rxn) == 3 if len(rxn[2]) == 2: print ' + '.join(rxn[0]), '<=>', ' + '.join(rxn[1]) else: print ' + '.join(rxn[0]), '->', ' + '.join(rxn[1])
def _parse_crn_file(self, filename): # Load data from filename into the proper bisimulation format if not os.path.isfile(filename): raise Exception( "File for unittest is missing: {}".format(filename)) crn, formal, _, _ = parse_crn_file(filename) crn = split_reversible_reactions(crn) return ([[Counter(part) for part in rxn] for rxn in crn], formal)
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 _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)
(b1, b2) = b basis += b1 basis_raw += b2 else: b = enumerate_basis(crn, fs) if b == None: # irregular or nontidy return None #TODO: do I see a bug here? what if !optimize & !inter2? (basis, basis_raw) = b if inter: return (basis, basis_raw) return basis if __name__ == "__main__": import sys from nuskell.parser import parse_crn_file, split_reversible_reactions crn_file = sys.argv[1] # # Add appropriate extensions if necessary. # if len(crn_file) < 4 or crn_file[-4:] != ".crn": crn_file += ".crn" (crn, formal_species, const_species) = parse_crn_file(crn_file) crn = split_reversible_reactions(crn) crn = remove_const(crn, const_species) basis = find_basis(crn, formal_species) if basis != None: print "Formal basis :" for (r, p) in basis: print_reaction([r, p])
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)