I've written a tool in Python to help me with a specific problem I have with electronic circuit design. Here are the motivations:
It is common in circuit design to need to choose two resistor values to form a voltage divider. Any number of combinations of resistors can satisfy the divider. And there are a lot of available resistor values to choose from. It is not uncommon for an engineer to just pick a resistor value out of thin air and solve for the other.
It is very desirable to reduce the number of line items in the BOM for a circuit board. In other words, the more resistor values I can share elsewhere in the same circuit, the better.
Prior to running this program, I have created lists of candidate resistor pairs and their combined cost in separate files. The contents of these JSON-encoded files look like this:
[[RA1, RA2, priceA],[RB1,RB2,priceB],[RC1,RC2,priceC],...]
Every pair of resistors in the same file will satisfy some specified voltage divider ratio. I have as many files as I have unique voltage dividers in the circuit.
My program then takes the multiple JSON files as input arguments, generates every permutation of resistor combinations, and tries to find which permutation produces the least number of unique resistor values. I also have it only show me the outputs with the lowest combined resistor price (many resistors are the same cost, so this helps pare down the results).
I am very new to Python and come from a long history of coding in C. I want to learn how to make this code more Pythonic. In particular, I'm convinced the embedded for-loops in the middle of the code can be replaced with something much more efficient.
resistor_bom_reducer.py:
"""
python3 resistor_bom_reducer.py file1.json file2.json file3.json ... fileN.json
"""
import json
import sys
import itertools
pairlists = []
totalperms = 1
# Read in JSON data from input arguements.
# pairlists is a list of lists representing every pair of resistors and their combined cost
for filename in sys.argv[1:]:
with open(filename) as json_data:
lst = json.load(json_data)
totalperms *= len(lst)
pairlists.append(lst)
print("Calculating permutations: %d" % totalperms)
perms = list(itertools.product(*pairlists))
print("Done")
# Loop through every permutation of resistors.
# combo is a list of flattened lists of every resistor combination
combo = [[0 for rows in range(len(pairlists)*2)] for cols in range(len(perms))]
price = [0 for x in range(len(perms))]
count = 0
for i in range(0,len(perms)):
for j in range(0,len(pairlists)):
combo[i][2*j] = perms[i][j][0]
combo[i][2*j+1] = perms[i][j][1]
price[i] += perms[i][j][2]
count += 1
if ( count % 1000000 == 0 ):
print("%d of %d" % (count,totalperms))
print("")
# Find the combination with the least number of unique resistor values
minlen = 999
for s in combo:
if ( len(set(s)) < len(pairlists)*2 ):
if ( len(set(s)) < minlen ):
minlen = len(set(s))
# Find the lowest combination price
minprice = 999.0
for s,p in zip(combo,price):
if ( len(set(s)) == minlen ):
if ( p < minprice ):
minprice = p
# Print only combinations of the lowest price and least number of unique resistor values
for s,p in zip(combo,price):
if ( len(set(s)) == minlen ):
if ( p == minprice ):
print(s,p)