代码在遍历 for 循环与 运行 一次时产生不同的结果

Code yields different results when iterating through for loops versus running once

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

有八个值(具有三种可能的状态)我想在每次迭代中独立更改。因此,我使用八个 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 文件时监督了一个问题还是有其他问题?

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

我们的想法是

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

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

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
====