bobbycar/akkuconfig/akkupack_config_greedy.py

158 lines
5.2 KiB
Python

#!/usr/bin/env python3
import numpy as np
import csv
import itertools
import math
distancemeasure="max" #mse, max
column_label=0
column_capacity=3
column_resistance=4
config_parallel=2
config_cells=12
#config_parallel*config_cells*config_packs needed
batteriesneeded=config_parallel*config_cells
batteries=[]
batterylabels=[]
with open('12S_LiIon_Akkupack_selected.csv', 'r') as csvfile:
csvreader = csv.reader(csvfile, delimiter=';')
firstrow=True
for row in csvreader:
label=row[column_label]
capacity=row[column_capacity]
resistance=row[column_resistance]
if not firstrow:
capacity=float(capacity)
resistance=float(resistance)
batteries.append([label,capacity,resistance])
#batterylabels.append(label)
firstrow=False
print(str(len(batteries))+" Batteries found")
if len(batteries)==batteriesneeded:
print("You have enough batteries for "+str(config_cells)+"S"+str(config_parallel)+"P")
elif len(batteries)>batteriesneeded:
print("You have "+str(len(batteries)-batteriesneeded)+" batteries in spare")
elif len(batteries)<batteriesneeded:
print("You need "+str(batteriesneeded-len(batteries))+" more batteries!")
exit()
#calculate mean capacity of all cells
meancapacity=0
for i in batteries:
meancapacity+=i[1] #add capacities
meancapacity/=len(batteries)
print("Mean Capacity= "+str(meancapacity))
comb_parallel_all=[]
for comb_parallel in itertools.combinations(batteries,config_parallel):
comb_parallel_all.append(comb_parallel)
comb_parallel_all_meancapacities=[]
for current_parallel in comb_parallel_all:
#print(current_parallel)
meancapacity_parallel=0
for current_cell_from_parallel in current_parallel:
meancapacity_parallel+=current_cell_from_parallel[1] #add capacities
meancapacity_parallel/=len(current_parallel)
#print("Mean Capacity Parallel set="+str(meancapacity_parallel))
comb_parallel_all_meancapacities.append( meancapacity_parallel )
deviationFromMean = [abs(x - meancapacity) for x in comb_parallel_all_meancapacities]
assert len(comb_parallel_all)==len(deviationFromMean), "Menacapacity array lenght not matching"
sortedIndices=np.argsort(deviationFromMean)
bestSelection=[]
bestSelectionDistance=10000000000
def getDistanceFromSelection(selection):
if distancemeasure=="mse":
return getDistanceFromSelectionMSE(selection)
elif distancemeasure=="max":
return getDistanceFromSelectionMAX(selection)
def getDistanceFromSelectionMSE(selection): #Mean Squared Error
global deviationFromMean
distance=0
for i in selection:
distance+= math.pow(deviationFromMean[i],2)
distance/=len(selection)
return distance
def getDistanceFromSelectionMAX(selection): #Mean Squared Error
global deviationFromMean
_deviations=[deviationFromMean[x] for x in selection]
distance=max(_deviations)
return distance
def greedy(parallelCombinations,remainingSortedIndices,currentSelection):
global config_cells
global bestSelection
global bestSelectionDistance
global deviationFromMean
#print("greedy("+str(len(parallelCombinations))+","+str(len(remainingSortedIndices))+","+str(currentSelection)+")")
if len(remainingSortedIndices)<1 or len(currentSelection)>=config_cells : #nothing left
currentSelectionDistance=getDistanceFromSelection(currentSelection)
if currentSelectionDistance < bestSelectionDistance: #new best found
bestSelectionDistance=currentSelectionDistance
bestSelection=currentSelection
print("")
print("New best found "+str(currentSelection))
_print_deviationFromMean=[round(deviationFromMean[a],1) for a in currentSelection]
print("Dev. from mean "+str(_print_deviationFromMean))
print("Distance="+str(currentSelectionDistance))
for i in bestSelection:
print(str(comb_parallel_all[i])+" mc="+str(comb_parallel_all_meancapacities[i]))
return #backtrack
if len(currentSelection)>0 and getDistanceFromSelection(currentSelection)>bestSelectionDistance: #distance is already too high
return #backtrack early
for i in remainingSortedIndices: #try all in sorted order
newremainingSortedIndices=[x for x in remainingSortedIndices] #copy list, should be the same for every i
_selectedIndex=i #greedy take element i
#remove elements with one of the used batteries
for used in parallelCombinations[_selectedIndex]:
#print(used)
for rsi in newremainingSortedIndices: #check all remaining indices
containesBattery=False
for pcb in parallelCombinations[rsi]:
if pcb==used:
containesBattery=True
if containesBattery:
newremainingSortedIndices=[x for x in newremainingSortedIndices if x is not rsi] #remove current index rsi from remainingSortedIndices
#repeat until empty
greedy(parallelCombinations,newremainingSortedIndices,currentSelection+[_selectedIndex])
greedy(comb_parallel_all,sortedIndices, [])
print(bestSelection)
print("###")
for i in bestSelection:
print(str(comb_parallel_all[i])+" mc="+str(comb_parallel_all_meancapacities[i]))