Example #1
0
  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')
Example #2
0
  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')
Example #3
0
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
Example #4
0
    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)
Example #5
0
  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')
Example #6
0
 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)
Example #7
0
    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)
Example #8
0
 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')
Example #9
0
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)
Example #10
0
 def _parse_crn_string(self, string):
     crn, formal, _, _ = parse_crn_string(string)
     crn = split_reversible_reactions(crn)
     return (crn, formal)