pythonstringrecursionsilent

I used a recursive function to modify a string, but if the string is too large the function returns nothing


I made a mutation function that changes every character in a string 1% of the time. To do this, I made a helper function that picks a character from a list and substitutes it in the old characters place. However, in the case where the new character picked matches the old character to be replaced, the mutation function is supposed to insert the old character twice. This makes things tricky because I can no longer just iterate through the string, since it might grow as it's iterated through. To solve this, I made the mutation function recursive. The code for this is below:

import sys
from numpy import random
from random import randrange

sys.setrecursionlimit(100000)

def PickRandomOtherBase(base_character):
    bases = ['A', 'C', 'G', 'T', '-'] 
    new_character = bases[randrange(0, len(bases))]
    if new_character == base_character.upper():
        return new_character + base_character.upper()
    else:
        return new_character

def AddMutations(sequence_string, mutation_rate=0.01):
    # base case
    if not sequence_string:
        return ''
    # otherwise
    rng = random.default_rng()
    m_flag = rng.binomial(1, mutation_rate)
    current_char = sequence_string[0]
    if m_flag:
        current_char = PickRandomOtherBase(current_char)
    return ''.join([current_char, AddMutations(sequence_string[1:], mutation_rate=mutation_rate)])

AddMutations('acgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctga',
mutation_rate=1)

This works for small strings, but for large strings it returns the following error: RecursionError: maximum recursion depth exceeded in comparison

I set the recursion limit using sys.setrecursionlimit(100000). I found through trial and error that, no matter how high I set the recursion limit, the function will not return anything if the input string is higher than about 2150 characters.

At this point I figure I can rewrite this code to just not be recursive, but I am stumped as to why this doesn't work. I didn't think the memory cost would be so high as to not function at all, and the silent failing isn't giving me much to work with in the way of troubleshooting.

When I try to print the function output with long strings, it prints nothing. It seems like there is a silent failure going on here too, because when I try to print anything, even the string 'foo' after calling this function on a long string, nothing is printed.


Solution

  • The code is reproducible, but missing a print for the result of AddMutations. It works otherwise :)

    Here is an iterative solution:

    from numpy import random
    from random import choice
    
    # single initialization globals
    bases = 'ACGT-'
    rng = random.default_rng()
    
    def PickRandomOtherBase(base_character):
        new_character = choice(bases)
        if new_character == base_character:
            return base_character * 2
        else:
            return new_character
    
    def AddMutations(sequence_string, mutation_rate=0.01):
        result = list(sequence_string.upper())  # Use a mutable list
        for i, c in enumerate(result):
            m_flag = rng.binomial(1, mutation_rate)
            if m_flag:
                result[i] = PickRandomOtherBase(c)  # mutate
        return ''.join(result)
    
    print(AddMutations('acgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctgaacgcgacgttggttaaccttaaacccgggttttgggtttgccaccgctga',
    mutation_rate=1))
    

    Output:

    CG-T-TCCATT-GG-TTC-GTTCGCGG--GGGA-GCGCTGG-TTGCGGCCCCGCCGT-A-GAAAC-ATTTCCTGG-A--CCGCTTTT-GGCCCCT-GAATTAGAC-T-C---TCTAA-ATTTCGAC-GGCGG-CCCGTTCCT--CC-GGAAA-TTCCCAGCAGGACC-GCCTGTTGGAA-T-CCACCCACTTAGG---TCCCCCG-AAGCCAAAGGTAATTGGGACGCGAGCCGGTTTC-AAAA-CT--CCGGA-AGGG-GCTTGA--GCCATGGATCTTCCAGGACTT-TTAAA-TT-GACG--CCACCCTAGAGGCGGGGTC-GT-AA-T-T-GCTTTAGGGCGCCCTAACCCC-T-GGCCACCC-CCCA-G-GGACCAAGCCG--CTTGCCATGGG-A--AATTAC-GTCATCCCCT--AGGTC-GGG-AT-G--TAAA-TGAACCACCAATCGCTTCGGTTTCGT-ACGCCGGGC--CAAT---TC-AATTATCCC--TT-GAACC-G--CTT-TTTTCAGGTT-GCTCCT-CC--TTCAACGTT-CA-C-A-CC-GGTACCTAAGGGTAATT--CTGGC-CTTGGGCCTTTACCC-CAA-ACCAGGCTTTTCACGAAAAGT-ACT-CCTG-CAATTTTAGGGGT-TT-TGAAAACCGG-CC-GTCGCGAGGCGT-ATTAAGG--ACTAATACCCC--G--A-GGCCCTAGTAA-AGGG-CAATTCCCCCTT-C-TTTTACCC-TGCGCCCCA--TT---CGGC-G--TCCCCCTGG--CCCGGGGAGGCACC-CTTTAATCCGATCAA-TAGG-CCCA-GGAGG-TTTTAAGTAGTCCCGGC-AC-TCACCTTGGATT-GGCCTG-G-GCCCCGGGCCGGCCAGGGGC-CGGATCACCACCA-TTTTGGGCAA-GT-CCTG-TGAGTC-TGATA-AC--TCCGG-GACGAGGCC-TAAAAGGGGCGAGG-CTTGTTT-ACC-CCAAGTTTTCTC-GTTAC-TTACCG-CGGTTAAAAGTA-GGTGT--ATCC---G---AA-GA-A-TGCCAATGGG-CTTGGGT-CC-T--GGGCCT-AC--CCTTGTTCCCCATTGAATGATTATC--TTTTC-TTTTCACC-CCTGG----CT-CCACTTCTT----CTAATTC--TTG-CGGTGG--CGGATTTT-A-CC-GGACCCGG-CCCTAGGAATT-AGG-CATGTT-G-TC-CCAAAT-GTTA-GGTATTTTATTAA-T-TCTTAATT-GGGGGGGAAGGTT-AACCCCCGCGAA-GTGC--GGTTCGGCGGTTTTTTC--TCCTT-TT-CTGC-AGT-AGTGGA-GAAGGGG-AAGGCCT-C-TT-TTC-CCATT-CA-CTAGG-GC-AACCC-AGGGGAGGG--CG-GGTTACC-CC-GATGGAGTTGGGCGGA--TTAGCCCCACCTTCAAAAACCCTAAACG-GGA-TTAAGCCG-GG-AAACCCCCATACTTGGGTA-CAACCAT-CCCG-ATC-CGAGTAA-AATTATT-TTTTTGGC-GCCATCATTCG-GGCCCCA--CA-TGAGG-CTGGCC-CTC-AT-C-CG-G--GCAATTACCACC-TTA-A-TTTTTTCCTA-TTTTA-AA-GGCCA--CGAAGG-GGAA-GTTGTCTG-A-GGGGCTTATTGGTAA-AACC-AACCTTCC--TGGT-TAAG-A-CGG-TTAAAAT-AGTGCACCAGGGGATTGAGGG-AACAGGGTCATGGCCACAA-TA-C-GCG-GGT-A--A-A-AAAAGGTGGG-AGATTCCCGG-GCATCCCTTT-GGGC--TATCACTTGGGACA-AACCA-CAAAA--GCCC-CTTAGGAGGCTT-TTAGGGTTGG-GAAAT-CGGG-A-GTTTGGCGAATG-G-GG-TTA-TGGTT-G--GGTTT-TTGGCCCC--CCAAGGG-TGGGCCAAAG-CGCCAAC---C-T-T-CC--C--GTTCATGGGCA-CCT-AATAAT-TGGGTGGAAAGGTTGCT-GTGGACCC-CACCGTGGTGTTAAGG-C-ATTGGA-CT-CCCTTTTTG-TCAA-TG-GG-CTT-GCCTC-C-TTTGGGGGTCG---T--AAA-TC-TGGATTGGAAAAGGGTGGGT-ATTAGGAAGTCCA---TCTGTA--ATT-GTGGC-G-T-TTGGT-AC-TAAAGGAAT-C-AGGTTC-AAAACCGTG-TACAA-GCTTTAGGG-TT-CCTCTCCGGACT-T-GGCCCTAC--TTAGAAT-TC--AA-CC-TTTAACCTTCA-TT-AACCTGTGGGGTTATT---AAAGTTTCT-TTC-CCCGATTCAAGT--A-CCGGCTTTCGAGGCCCC-T-ACCAA-T-CTTC-GG--GGTCA-TCCAGGCTCCCGGGGC-AC-TTGGGGGGGGG-G-T-GATACAACGACC-AA-ATTA--TTA-CA-CGG---GCCCA-CCA-GGAGGCTTAT--AA-AGGGAGGCTCCATA-TTTTGACTTCAAAACC-CAAAAA-CCATAACTT-GAAA-GCA--TAAACC-ACT-G-CAC-TA-TTTCC-GC-TAG-CT-G--ACCTTAA-GGGG-GAC-GTGTGG-GTTAATGGAACA-AACCATTTGT-CACAAAATACCT---CA-CAGGC-ACGTGGCC-TCGG-