【问题标题】:Code yields different results when iterating through for loops versus running once当迭代 for 循环与运行一次时,代码会产生不同的结果
【发布时间】:2021-09-14 08:41:15
【问题描述】:

我编写了一个脚本,它编辑了一个模拟程序 (LTspice) 的 .txt 文件,然后使用修改后的 .txt 文件运行模拟。

我想为每次迭代独立更改八个值(具有三种可能的状态)。因此,我使用 8 个 for 循环通过搜索和替换 .txt 文件中的字符串来遍历所有组合。这看起来像这样:

Txt_original = 'SIM_COM_Automated_Copy.txt' #LTSpice output file has to be copied manually first

rawDataFile = 'SIM_COM_Automated_Copy.raw'

list1 =[]
list2 = []

with open(Txt_original, 'rb') as file:
        Data_backup = file.read()

resistorValues = [['Res1=1980', 'Res1=2000', 'Res1=2020'],['Res2=1980', 'Res2=2000', 'Res2=2020'], ['Res3=1980', 'Res3=2000', 'Res3=2020'], ['Res4=1980', 'Res4=2000', 'Res4=2020'], ['Res7=19800', 'Res7=20000', 'Res7=20200'], ['Res8=9900', 'Res8=10000', 'Res8=10100'], ['Res16=19800', 'Res16=20000', 'Res16=20200'], ['Res17=9900', 'Res17=10000', 'Res17=10100']] 

count = 0

for a in range(1,3):
    editSimParameters(Txt_original, resistorValues[0][0], resistorValues[0][a] ) #Res1
    for b in range(1,3):
        editSimParameters(Txt_original, resistorValues[1][0], resistorValues[1][b] ) #Res2
        for c in range(1,3):
            editSimParameters(Txt_original, resistorValues[2][0], resistorValues[2][c] ) #Res3
            for d in range(1,3):
                editSimParameters(Txt_original, resistorValues[3][0], resistorValues[3][d] ) #Res4
                for e in range(1,2):
                    editSimParameters(Txt_original, resistorValues[4][0], resistorValues[4][e] ) #Res7
                    for f in range(1,2):
                        editSimParameters(Txt_original, resistorValues[5][0], resistorValues[5][f] ) #Res8
                        for g in range(1,2):
                            editSimParameters(Txt_original, resistorValues[6][0], resistorValues[6][g] ) #Res16
                            for h in range(1,2):
                                editSimParameters(Txt_original, resistorValues[7][0], resistorValues[7][h] ) #Res17
                                runSimulation(Txt_original)
                                #time.sleep(10)
                                result = evaluateResults(rawDataFile)
                                valueSet = [a, b, c, d, e, f, g, h]
                                
                                if valueSet == [2,2,2,2,1,1,1,1]:
                                    print('Res1= '+resistorValues[0][a])
                                    print('Res2= '+resistorValues[1][b])
                                    print('Res3= '+resistorValues[2][c])
                                    print('Res4= '+resistorValues[3][d])
                                    print('Res7= '+resistorValues[4][e])
                                    print('Res8= '+resistorValues[5][f])
                                    print('Res16= '+resistorValues[6][g])
                                    print('Res17= '+resistorValues[7][h])
                                    print('The result of the combination ' + str(valueSet) + ' is ' + str(result))
                                
                                list1.append(result)
                                list2.append(valueSet)

                                    
                                with open(Txt_original, 'wb') as file:  #Reset the working file
                                    file.write(Data_backup)
                                
                                #Progress Tracking
                                count = count +1        

                                if count%25 == 0:
                                    print(count)

editSimParameters() 函数如下所示:

def editSimParameters(workingFile, oldParam, newParam):
    with open(workingFile, 'rb') as file:
        Data_original = file.read() 
        Data_temp = Data_original.replace(oldParam.encode('utf-8'), newParam.encode('utf-8'))
    
    with open(workingFile, 'wb') as file:
        file.write(Data_temp)

我在这个例子中减少了循环迭代的次数,以便代码更快地终止。尽管如此,在运行此代码时,组合 [2,2,2,2,1,1,1,1] 的结果与我通过更改 for 循环获得的相同组合的结果不同,因此只有这种组合被执行:

迭代后的结果(共16次模拟):组合[2,2,2,2,1,1,1,1]的结果为16.347881

改变 for 循环的结果(1 个模拟):组合 [2, 2, 2, 2, 1, 1, 1, 1] 的结果是 16.327114

仅进行一次模拟的结果是正确的,我通过手动进行了模拟验证。

在迭代和更改 .txt 文件时,我是在监督问题,还是有其他问题?

【问题讨论】:

  • 圣巢蝙蝠侠。
  • 我认为你最好阅读一次“模板文件”并发布它的修改版本。鉴于您的代码结构,很难找到错误(如果有的话)在哪里......
  • 请检查您没有做类似"1234".replace("1","2").replace("2","3").replace("3","4").replace("4","5") 的事情,并且想从中获得“2345”......因为如果将是“5555”。

标签: python for-loop iteration


【解决方案1】:

这是您似乎正在尝试做的一个非常简化(并且更强大)的版本,使用 itertools.product 和正则表达式来替换电阻值。

我们的想法是

  • 读取您的原​​始 LTSpice 文件(我手头没有,因此源代码中有一个字符串常量)
  • 设置一个字典,将电阻名称与那些电阻应尝试使用的值匹配
  • 使用一些温和的zip 魔法将字典按摩成itertools.product 接受的形式
  • 使用itertools.product 生成值的笛卡尔积,然后使用zip 将它们与键返回以得到combo dict
  • 循环组合并使用re.sub 将这些值替换为模板(副本)。
  • 而不是像我们在这里做的print()data,你应该把它写到你提供给模拟器的文件中,然后在那里做你必须做的事情。 我建议不要覆盖原始模板文件。

您可以根据需要向resistor_combos dict 添加任意数量的键和值,它们都会被彻底检查。

import itertools
import re

# Would be read from the original SIM_COM_Automated_Copy file
template = """
Res1=100
Res2=100
Res8=1000
""".strip()

resistor_combos = {
    "Res1": [123, 456],
    "Res2": [789, 126],
}

resistor_keys, resistor_values = zip(*resistor_combos.items())

for value_combo in itertools.product(*resistor_values):
    combo = dict(zip(resistor_keys, value_combo))
    data = template  # "Copy" the template for modification
    for key, value in combo.items():
        data = re.sub(f"^{key}=(\d+)", f"{key}={value}", data, flags=re.MULTILINE)
    print(combo)
    print(data)
    print("====")

打印出来

{'Res1': 123, 'Res2': 789}
Res1=123
Res2=789
Res8=1000
====
{'Res1': 123, 'Res2': 126}
Res1=123
Res2=126
Res8=1000
====
{'Res1': 456, 'Res2': 789}
Res1=456
Res2=789
Res8=1000
====
{'Res1': 456, 'Res2': 126}
Res1=456
Res2=126
Res8=1000
====

【讨论】:

    猜你喜欢
    • 2020-01-28
    • 1970-01-01
    • 1970-01-01
    • 2013-03-08
    • 2019-12-19
    • 2021-08-18
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多