python 中的部分列表,索引有问题
parts of lists in python, troubles with indexes
我是 python 的新手,列表和索引给我带来了一些麻烦。
我想做的是:
',
获取代表 RPN 表达式的两个个体,个体 1 和个体 2 作为示例:
i1=['3', 'x', '*', '3' ,'4' ,'*', '/']
i2=['x', '4', '/', 'x' ,'4' ,'+', '-']
然后,获取它们的子集并交换子集,如下所示:
我从 i1 中获取子集 ['3','4','*'] 并从 i2 ['4'](最后的 3)中获取子集,然后交叉生成两个输出:
out1=['3', 'x', '*','4' , '/']
out2=['x', '3' ,'4' ,'*', '/', 'x' ,'6' ,'+', '-']
我做的代码如下,它一直给我错误的结果,比如差一个错误,我不想进入 for 循环路线,因为我敢打赌还有更多 pythonesque 方式这样做。谁能帮我一把?
def crossover(individual1,individual2,treedepth):
from commonfunctions import getDepth,traverse,get_random_operator
from commonfunctions import isOperator
from generators import generate_RPN_expr
#simple element mutation
cxposindividual1 = random.randint(0, len(individual1) - 1)
cxposindividual2 = random.randint(0, len(individual2) - 1)
subtree1=traverse(individual1,cxposindividual1)
subtree2 = traverse(individual2, cxposindividual2)
individual1depth=getDepth(individual1)
individual2depth = getDepth(individual2)
subtree1depth=getDepth(subtree1)
subtree2depth = getDepth(subtree2)
output1=list()
output1[:]=[]
output2=list()
output2[:]=[]
#todo debug this !!!!
#verificar se ecsolhemos um operador ou um nó terminal
output1 = individual1[:len(individual1)+1-cxposindividual1-len(subtree1)]+subtree2+individual1[len(individual1)-cxposindividual1+1:]
output2 = individual2[:len(individual2) + 1 - cxposindividual2 - len(subtree2)] + subtree1 + individual2[len(individual2) - cxposindividual2 + 1:]
if len(output1) == 2 or len(output2) == 2:
print('argh>>>') # problema !!!!
#print ('CX')
return (output1,output2)
遍历函数returns选中位置的子树。 getDepth 尚未使用。
谢谢
豪尔赫
新代码
def crossover(individual1,individual2,treedepth):
from commonfunctions import getDepth,traverse,get_random_operator,traverse_with_indexes
from commonfunctions import isOperator
r1 = random.randrange(len(individual1))
r2 = random.randrange(len(individual2))
st1 = traverse(individual1, r1)
st2 = traverse(individual2, r2)
slice1 = slice(r1, r1+len(st1))
slice2 = slice(r2, r2+len(st2))
i1,i2 = individual1[:],individual2[:]
a,b=i1[slice1],i2[slice2]
i1[slice1],i2[slice2] = i2[slice2],i1[slice1]
return i1, i2
这里,个人 1 等于 ['3.8786681846845', 'x', '+'] 和 st1 = ['x'] 切片是 2,3 我认为它应该是 1,2但 ...
其中个人 2 = ['x'] st2 = ['x'] 切片是 0,1 很好 !!!
我很想用 sizesfor exceptions 制作一些 if 块,但我不喜欢 exceptions
谢谢
我怀疑您的问题是因为 python 中的 切片 不包含它们的最终索引。也就是说,[0:1] 是一个只包含一个元素 [0] 的切片。
你的例子:
i1=['3', 'x', '*', '3' ,'4' ,'*', '/']
i2=['x', '4', '/', 'x' ,'4' ,'+', '-']
# 0 1 2 3 4 5 6
然后:
temp1 = i1[3:6] # 3,4,*
temp2 = i2[1:2] # 4
然后:
print(i1)
print(i2)
i1[3:6] = temp2
i2[1:2] = temp1
print(i1)
print(i2)
最后,因为牛逼,你可以这样做:
i1[3:6],i2[1:2] = i2[1:2],i1[3:6]
或者这样:
A = slice(3,6)
B = slice(1,2)
i1[A],i2[B] = i2[B],i1[A]
编辑
更进一步,您可以使用 random.randrange()
来避免 fencepost 错误,并执行以下操作:
def crossover(individual1,individual2,treedepth):
r1 = random.randrange(len(individual1))
r2 = random.randrange(len(individual2))
st1 = traverse(individual1, r1)
st2 = traverse(individual2, r2)
slice1 = slice(r1, r1+len(st1))
slice2 = slice(r2, r2+len(st2))
# fazer pseudonimos
i1,i2 = individual1,individual2
# o fazer copias
i1,i2 = individual1[:],individual2[:]
i1[slice1],i2[slice2] = i2[slice2],i1[slice1]
return i1, i2
遍历函数
这个函数的目的是return从位置start开始的'有意义的子树,(因为程序是一个rpn表示)
def traverse(inputexpr,start):
from copy import copy,deepcopy
components=list()
components[:]=[]
components=inputexpr[0:len(inputexpr)-start+1]
components.reverse()
pos=0
result=list()
result[:]=[]
score=0
if isOperator(components[pos]):
result.append(components[pos])
score=score+getArity(components[pos])
else:
result.append(components[pos])
score=score -1
pos=pos+1
while score>0:
if isOperator(components[pos]):
result.append(components[pos])
score = score + getArity(components[pos])-1
else:
result.append(components[pos])
score = score - 1
pos = pos + 1
result.reverse()
return result
第二次编辑
考虑这个重新实现。这是否符合您的要求?
_Arity = {op:2 for op in '*/+-%'}
def getArity(op):
return _Arity[op] if op in _Arity else 0
def isOperator(op):
return op in _Arity
def traverse(inputexpr, pos):
"""
Return the meaningful subtree of inputexpr that has its upper node
at position pos. Given an input like this:
[ A, B, +, 5, * ]
# 0 1 2 3 4
Here are the expected results:
0: [ A ]
1: [ B ]
2: [ A B + ]
3: [ 5 ]
4: [ A B + 5 * ]
"""
chop = pos + 1
subtree = inputexpr[:chop]
score = 1
while score:
chop -= 1
score += getArity(subtree[chop]) - 1
return subtree[chop:]
i1=['3', 'x', '*', '3' ,'4' ,'*', '/']
i2=['x', '4', '/', 'x' ,'4' ,'+', '-']
for i in range(len(i1)):
print("#: {}, subtree= {}".format(i, traverse(i1, i)))
终于按预期工作了
#output tree
output1=list()
output1[:]=[]
output2=list()
output2[:]=[]
i1p1 = individual1[:len(individual1) - len(subtree1) - cxposindividual1]
i1p2 = subtree2
i1p3 = individual1[len(i1p1) + len(subtree1):]
i2p1 = individual2[:len(individual2) - len(subtree2) - cxposindividual2]
i2p2 = subtree1
i2p3 = individual2[len(i2p1) + len(subtree2):]
output1=i1p1+i1p2+i1p3
output2=i2p1+i2p2+i2p3
非常感谢 Austin,多亏了你,我发现了困扰我其他 bug 的 bug。
让它工作后,我将以更 python 风格的方式实现它。
现在我正在使用这个非常冗长的代码,所以我不会在语言细节中得到很多。
再次感谢
我是 python 的新手,列表和索引给我带来了一些麻烦。
我想做的是: ', 获取代表 RPN 表达式的两个个体,个体 1 和个体 2 作为示例:
i1=['3', 'x', '*', '3' ,'4' ,'*', '/']
i2=['x', '4', '/', 'x' ,'4' ,'+', '-']
然后,获取它们的子集并交换子集,如下所示:
我从 i1 中获取子集 ['3','4','*'] 并从 i2 ['4'](最后的 3)中获取子集,然后交叉生成两个输出:
out1=['3', 'x', '*','4' , '/']
out2=['x', '3' ,'4' ,'*', '/', 'x' ,'6' ,'+', '-']
我做的代码如下,它一直给我错误的结果,比如差一个错误,我不想进入 for 循环路线,因为我敢打赌还有更多 pythonesque 方式这样做。谁能帮我一把?
def crossover(individual1,individual2,treedepth):
from commonfunctions import getDepth,traverse,get_random_operator
from commonfunctions import isOperator
from generators import generate_RPN_expr
#simple element mutation
cxposindividual1 = random.randint(0, len(individual1) - 1)
cxposindividual2 = random.randint(0, len(individual2) - 1)
subtree1=traverse(individual1,cxposindividual1)
subtree2 = traverse(individual2, cxposindividual2)
individual1depth=getDepth(individual1)
individual2depth = getDepth(individual2)
subtree1depth=getDepth(subtree1)
subtree2depth = getDepth(subtree2)
output1=list()
output1[:]=[]
output2=list()
output2[:]=[]
#todo debug this !!!!
#verificar se ecsolhemos um operador ou um nó terminal
output1 = individual1[:len(individual1)+1-cxposindividual1-len(subtree1)]+subtree2+individual1[len(individual1)-cxposindividual1+1:]
output2 = individual2[:len(individual2) + 1 - cxposindividual2 - len(subtree2)] + subtree1 + individual2[len(individual2) - cxposindividual2 + 1:]
if len(output1) == 2 or len(output2) == 2:
print('argh>>>') # problema !!!!
#print ('CX')
return (output1,output2)
遍历函数returns选中位置的子树。 getDepth 尚未使用。
谢谢
豪尔赫
新代码
def crossover(individual1,individual2,treedepth):
from commonfunctions import getDepth,traverse,get_random_operator,traverse_with_indexes
from commonfunctions import isOperator
r1 = random.randrange(len(individual1))
r2 = random.randrange(len(individual2))
st1 = traverse(individual1, r1)
st2 = traverse(individual2, r2)
slice1 = slice(r1, r1+len(st1))
slice2 = slice(r2, r2+len(st2))
i1,i2 = individual1[:],individual2[:]
a,b=i1[slice1],i2[slice2]
i1[slice1],i2[slice2] = i2[slice2],i1[slice1]
return i1, i2
这里,个人 1 等于 ['3.8786681846845', 'x', '+'] 和 st1 = ['x'] 切片是 2,3 我认为它应该是 1,2但 ...
其中个人 2 = ['x'] st2 = ['x'] 切片是 0,1 很好 !!!
我很想用 sizesfor exceptions 制作一些 if 块,但我不喜欢 exceptions
谢谢
我怀疑您的问题是因为 python 中的 切片 不包含它们的最终索引。也就是说,[0:1] 是一个只包含一个元素 [0] 的切片。
你的例子:
i1=['3', 'x', '*', '3' ,'4' ,'*', '/']
i2=['x', '4', '/', 'x' ,'4' ,'+', '-']
# 0 1 2 3 4 5 6
然后:
temp1 = i1[3:6] # 3,4,*
temp2 = i2[1:2] # 4
然后:
print(i1)
print(i2)
i1[3:6] = temp2
i2[1:2] = temp1
print(i1)
print(i2)
最后,因为牛逼,你可以这样做:
i1[3:6],i2[1:2] = i2[1:2],i1[3:6]
或者这样:
A = slice(3,6)
B = slice(1,2)
i1[A],i2[B] = i2[B],i1[A]
编辑
更进一步,您可以使用 random.randrange()
来避免 fencepost 错误,并执行以下操作:
def crossover(individual1,individual2,treedepth):
r1 = random.randrange(len(individual1))
r2 = random.randrange(len(individual2))
st1 = traverse(individual1, r1)
st2 = traverse(individual2, r2)
slice1 = slice(r1, r1+len(st1))
slice2 = slice(r2, r2+len(st2))
# fazer pseudonimos
i1,i2 = individual1,individual2
# o fazer copias
i1,i2 = individual1[:],individual2[:]
i1[slice1],i2[slice2] = i2[slice2],i1[slice1]
return i1, i2
遍历函数
这个函数的目的是return从位置start开始的'有意义的子树,(因为程序是一个rpn表示)
def traverse(inputexpr,start):
from copy import copy,deepcopy
components=list()
components[:]=[]
components=inputexpr[0:len(inputexpr)-start+1]
components.reverse()
pos=0
result=list()
result[:]=[]
score=0
if isOperator(components[pos]):
result.append(components[pos])
score=score+getArity(components[pos])
else:
result.append(components[pos])
score=score -1
pos=pos+1
while score>0:
if isOperator(components[pos]):
result.append(components[pos])
score = score + getArity(components[pos])-1
else:
result.append(components[pos])
score = score - 1
pos = pos + 1
result.reverse()
return result
第二次编辑
考虑这个重新实现。这是否符合您的要求?
_Arity = {op:2 for op in '*/+-%'}
def getArity(op):
return _Arity[op] if op in _Arity else 0
def isOperator(op):
return op in _Arity
def traverse(inputexpr, pos):
"""
Return the meaningful subtree of inputexpr that has its upper node
at position pos. Given an input like this:
[ A, B, +, 5, * ]
# 0 1 2 3 4
Here are the expected results:
0: [ A ]
1: [ B ]
2: [ A B + ]
3: [ 5 ]
4: [ A B + 5 * ]
"""
chop = pos + 1
subtree = inputexpr[:chop]
score = 1
while score:
chop -= 1
score += getArity(subtree[chop]) - 1
return subtree[chop:]
i1=['3', 'x', '*', '3' ,'4' ,'*', '/']
i2=['x', '4', '/', 'x' ,'4' ,'+', '-']
for i in range(len(i1)):
print("#: {}, subtree= {}".format(i, traverse(i1, i)))
终于按预期工作了
#output tree
output1=list()
output1[:]=[]
output2=list()
output2[:]=[]
i1p1 = individual1[:len(individual1) - len(subtree1) - cxposindividual1]
i1p2 = subtree2
i1p3 = individual1[len(i1p1) + len(subtree1):]
i2p1 = individual2[:len(individual2) - len(subtree2) - cxposindividual2]
i2p2 = subtree1
i2p3 = individual2[len(i2p1) + len(subtree2):]
output1=i1p1+i1p2+i1p3
output2=i2p1+i2p2+i2p3
非常感谢 Austin,多亏了你,我发现了困扰我其他 bug 的 bug。 让它工作后,我将以更 python 风格的方式实现它。 现在我正在使用这个非常冗长的代码,所以我不会在语言细节中得到很多。
再次感谢