I am using python-3.x, and I am trying to do mutation on a binary string that will flip one bit of the elements from 0 to 1 or 1 to 0 by random, I tried some methods but didn't work I don't know where is the problem:
x=[0, 0, 0, 0, 0]
def mutation (x, muta):
for i in range(len(x)):
if random.random() < muta:
x[i] = type(x[i])(not x[i])
return x,
print (x)
The output for example should be x=[0, 0, 0, 1, 0] or x=[1, 0, 0, 0, 0] and so on....
Also, I tried this one:
MUTATION_RATE = 0.5
CHROMO_LEN = 6
def mutate(x):
x = ""
for i in range(CHROMO_LEN):
if (random.random() < MUTATION_RATE):
if (x[i] == 1):
x += 0
else:
x += 1
else:
x += x[i]
return x
print(x)
please any suggestion or advice will be appreciated
Are you sure you're calling the function before printing x:
def mutation(x):
# your code without the trailing comma
mutation(x)
print(x)
In Python, creating a new list is usually preferable to mutating an old one. I would write your first function like this (I converted the integers to booleans because you're just flipping them:
x = [False, False, False, False]
def mutation(x, muta):
return [not e if random.random() < muta else e
for e in x]
Change x by assigning to it again:
x = mutation(x, .5)
Your original function is working if you remove the comma after the return:
def mutation(x, muta):
for i in range(len(x)):
if random.random() < muta:
x[i] = type(x[i])(not x[i])
return x
x = [False, False, False, False]
mutation(x, .5)
Out[8]: [False, False, True, False]
mutation(x, .5)
Out[9]: [True, True, True, False]
You could also use python's XOR operator to flip bits, which will flip between '1' and '0':
x[1] = x[1] ^ 1
See also: Python XOR preference: bitwise operator vs. boolean operators
Related
I have created a sequence alignment tool to compare two strands of DNA (X and Y) to find the best alignment of substrings from X and Y. The algorithm is summarized here (https://en.wikipedia.org/wiki/Smith–Waterman_algorithm). I have been able to generate a lists of lists, filling them all with zeros, to represent my matrix. I created a scoring algorithm to return a numerical score for each kind of alignment between bases (eg. plus 4 for a match). Then I created an alignment algorithm that should put a score in each coordinate of my "matrix". However, when I go to print the matrix, it only returns the original with all zeros (rather than actual scores).
I know there are other methods of implementing this method (with numpy for example), so could you please tell me why this specific code (below) does not work? Is there a way to modify it, so that it does work?
code:
def zeros(X: int, Y: int):
lenX = len(X) + 1
lenY = len(Y) + 1
matrix = []
for i in range(lenX):
matrix.append([0] * lenY)
def score(X, Y):
if X[n] == Y[m]: return 4
if X[n] == '-' or Y[m] == '-': return -4
else: return -2
def SmithWaterman(X, Y, score):
for n in range(1, len(X) + 1):
for m in range(1, len(Y) + 1):
align = matrix[n-1, m-1] + (score(X[n-1], Y[m-1]))
indelX = matrix[n-1, m] + (score(X[n-1], Y[m]))
indelY = matrix[n, m-1] + (score(X[n], Y[m-1]))
matrix[n, m] = max(align, indelX, indelY, 0)
print(matrix)
zeros("ACGT", "ACGT")
output:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
The reason it's just printing out the zeroed out matrix is that the SmithWaterman function is never called, so the matrix is never updated.
You would need to do something like
# ...
SmithWaterman(X, Y, score)
print(matrix)
# ...
However, If you do this, you will find that this code is actually quite broken in many other ways. I've gone through and annotated some of the syntax errors and other issues with the code:
def zeros(X: int, Y: int):
# ^ ^ incorrect type annotations. should be str
lenX = len(X) + 1
lenY = len(Y) + 1
matrix = []
for i in range(lenX):
matrix.append([0] * lenY)
# A more "pythonic" way of expressing the above would be:
# matrix = [[0] * len(Y) + 1 for _ in range(len(x) + 1)]
def score(X, Y):
# ^ ^ shadowing variables from outer scope. this is not a bug per se but it's considered bad practice
if X[n] == Y[m]: return 4
# ^ ^ variables not defined in scope
if X[n] == '-' or Y[m] == '-': return -4
# ^ ^ variables not defined in scope
else: return -2
def SmithWaterman(X, Y, score): # this function is never called
# ^ unnecessary function passed as parameter. function is defined in scope
for n in range(1, len(X) + 1):
for m in range(1, len(Y) + 1):
align = matrix[n-1, m-1] + (score(X[n-1], Y[m-1]))
# ^ invalid list lookup. should be: matrix[n-1][m-1]
indelX = matrix[n-1, m] + (score(X[n-1], Y[m]))
# ^ out of bounds error when m == len(Y)
indelY = matrix[n, m-1] + (score(X[n], Y[m-1]))
# ^ out of bounds error when n == len(X)
matrix[n, m] = max(align, indelX, indelY, 0)
# this should be nested in the inner for-loop. m, n, indelX, and indelY are not defined in scope here
print(matrix)
zeros("ACGT", "ACGT")
def large_sum(lst, num):
def larger(x):
return (int(x) > num)
m = list(map(larger,lst))
print(m)
large_sum([2,4,6,8,10], 7)
# [False, False, False, True, True]
I wish to get the sum of the element in [2,4,6,8,10] where m is True.
You can use itertools.compress in the following way:
from itertools import compress
def large_sum(lst, num):
def larger(x):
return (int(x) > num)
m = list(map(larger,lst))
return m
l = [2,4,6,8,10]
n = 7
res = large_sum(l, n)
print(sum(list(compress(l, res)))
I kept the original logic, but I would suggest to use #chris method as it would be better efficency-wise:
l = [2,4,6,8,10]
n = 7
sum(i for i in l if i > n)
The main thing is to use filter instead of map:
def large_sum(lst, num):
def larger(x):
return x > num
return sum(filter(larger, lst))
print(large_sum([2,4,6,8,10], 7))
# 18
map transforms each value in the list, into a boolean in this case. The original values are not there anymore, and if you sum the booleans, True is converted to 1 and False to 0, which is why you get 2.
filter, on the other hand, returns the original values, but only those for which the predicate (larger in this case) returns True, and omits the others. Then you just sum those.
Suppose I have constraints: [x > 2, y > 1, x < 10], and I want to add condition x%4 == 0 when y==1, and get all results, how would I do that in Z3?
I've add blocking constraint for solved result and iterate it to get all possible SAT result, but I found out that it'll simply ignore value y == 1.
Below is the code that I used to test, where it yield no solution.
>>> x, y = Ints('x y')
>>> x = If(y == 1, x%4==0, x)
>>> F = [x > 2, y == 1, x < 10]
>>> solve(F)
no solution
You can use logical implication:
Implies(y == 1, (x % 4) == 0)
This is semantically equivalent to #Axel Kemper's answer, but I believe is more direct logically and doesn't need the else clause. (It also restricts the then branch to be a boolean, providing a bit more type-safety. This is important in a language like Python where everything is dynamically typed.)
What about this?
from z3 import *
x, y = Ints('x y')
s = Solver()
s.add(x > 2, y == 1, x < 10)
s.add(If(y == 1, (x % 4) == 0, True))
print(s.check())
print(s.model())
For y == 1 the constraint is fulfilled, if (x % 4) == 0.
Otherwise, the constraint is fulfilled anyhow.
>>> fibonacci = [0,1,1,2,3,5,8,13,21,34,55]
>>> odd_numbers = list(filter(lambda x: x % 2, fibonacci))
>>> print(odd_numbers)
[1, 1, 3, 5, 13, 21, 55]
>>> even_numbers = list(filter(lambda x: x % 2 == 0, fibonacci))
>>> print(even_numbers)
[0, 2, 8, 34]
why not like this: lambda x: x % 2 == 1
It is because x % 2 will be read as a boolean and 0 is false and 1 is true (like every number different of 0).
You can try it with
print (True == 1) # True
print (False == 0) # True
Try it online!
In boolean context, non-zero is true (and zero is false). Your version is quite legal as well, it's mostly save some typing.
It is because (x % 2) would return 1 if x is divisible by 2 else 0.Now in Boolean context
1 is for True and 0 is for False.Therefore, in filter function we use only x%2 for getting the odd numbers, because it will give 0(False) if it is divisible by 2 else 1(True).
This behaviour is due to filter function rather than lambda here.
filter definition:
As the name suggests, filter creates a list of elements for which a function returns true.
filter(func, iterable) ---> func is the function which will be executed on iterable.
So now lets see how will filter work in this case.
fibonacci = [0,1,1,2,3,5,8,13,21,34,55]
odd_numbers = list(filter(lambda x: x % 2, fibonacci))
# For each element in fibonacci:
# x = fibonacci[0]
# lambda x: x % 2 will return 0 which is equivalent to False
# Now filter will ignore this as the result of filter is False
# Next Iteration: x = fibonacci[1]
# lambda x: x % 2 will return 1 which is equivalent to True
# So filter will get this value
# therefore, odd_numbers = [1]
# So on and so forth.
Hope it helps.
I went onto one line of code, which I want to convert from numpy syntax to regular python 2.7 syntax:
SunAz=SunAz + (SunAz < 0) * 360
source:
https://github.com/Sandia-Labs/PVLIB_Python/blob/master/pvlib/pvl_ephemeris.py#L147
If we pretend that the numpy array is one dimensional, can it be translated to regular python 2.7 syntax like so:
newSunAz = []
for item in SunAz:
if item < 0:
newItem = item + item*360
newSunAz.append(newItem)
else:
newSunAz.append(item)
??
Thank you for the help.
I'm not sure that this would be the translation. The line
SunAz=SunAz + (SunAz < 0) * 360
(SunAz < 0) creates a boolean array, True where the angle is negative, and false otherwise. Multiplying False by a constant gives 0, and True is interpreted to be a 1. This line actually says, "shift the angle by 360 degrees if negative, otherwise leave it be".
So a more literal translation would be the following:
SunAz = [angle + 360 if angle < 0 else angle for angle in SunAz]
Try this:
new_sun_az = [i+360 if i > 0 else i for i in sun_az]
The main difference is that most operators are applied to the list object in plain Python lists and return a single result, while they return a numpy array where each item is the result of the operation applied to the corresponding item on the original array for numpy arrays.
>>> import numpy as np
>>> plainlist = range(5)
>>> plainlist
[0, 1, 2, 3, 4]
>>> plainlist > 5 # single result
True
>>> nparray = np.array(plainlist)
>>> nparray
array([0, 1, 2, 3, 4])
>>> nparray > 5 # array of results
array([False, False, False, False, False], dtype=bool)
>>>
[update]
Mike's answer is right. My original answer was:
new_sun_az = [i+i*360 if i > 0 else i for i in sun_az]