+sub seq_insert
+{
+ # Martin A. Hansen, June 2009.
+
+ # Randomly duplicates a given number of residues in a given sequence.
+
+ my ( $seq, # sequence to mutate
+ $insertions, # number of residues to insert
+ ) = @_;
+
+ # Returns a string.
+
+ my ( $i, $pos );
+
+ for ( $i = 0; $i < $insertions; $i++ )
+ {
+ $pos = int( rand( length $seq ) );
+
+ substr $seq, $pos, 0, substr $seq , $pos, 1;
+ }
+
+ return $seq;
+}
+
+
+sub seq_delete
+{
+ # Martin A. Hansen, June 2009.
+
+ # Randomly deletes a given number of residues from a given sequence.
+
+ my ( $seq, # sequence to mutate
+ $deletions, # number of residues to delete
+ ) = @_;
+
+ # Returns a string.
+
+ my ( $i, $pos );
+
+ for ( $i = 0; $i < $deletions; $i++ )
+ {
+ $pos = int( rand( length $seq ) );
+
+ substr $seq, $pos, 1, '';
+ }
+
+ return $seq;
+}
+
+
+sub seq_mutate
+{
+ # Martin A. Hansen, June 2009.
+
+ # Introduces a given number of random mutations in a
+ # given sequence of a specified alphabet.
+
+ my ( $seq, # sequence to mutate
+ $mutations, # number of mutations
+ $alph, # alphabet of sequence
+ ) = @_;
+
+ # Returns a string.
+
+ my ( $i, $pos, %lookup_hash );
+
+ $i = 0;
+
+ while ( $i < $mutations )
+ {
+ $pos = int( rand( length $seq ) );
+
+ if ( not exists $lookup_hash{ $pos } )
+ {
+ substr $seq, $pos, 1, res_mutate( substr( $seq , $pos, 1 ), $alph );
+
+ $lookup_hash{ $pos } = 1;
+
+ $i++;
+ }
+ }
+
+ return $seq;
+}
+
+
+sub res_mutate
+{
+ # Martin A. Hansen, June 2009.
+
+ # Mutates a given residue to another from a given alphabet.
+
+ my ( $res, # residue to mutate
+ $alph, # alphabet
+ ) = @_;
+
+ # Returns a char.
+
+ my ( $alph_len, $new );
+
+ $alph_len = scalar @{ $alph };
+ $new = $res;
+
+ while ( uc $new eq uc $res ) {
+ $new = $alph->[ int( rand( $alph_len ) ) ];
+ }
+
+ return POSIX::islower( $res ) ? lc $new : uc $new;
+}
+
+