From bca06084124f354abb3d649dd781a001c0a0f510 Mon Sep 17 00:00:00 2001 From: Tom Barbette Date: Sat, 3 Aug 2024 11:29:57 +0200 Subject: [PATCH] ZLT: Support for output variable in percent use zlp instead of zlt --- integration/zlt.npf | 2 ++ npf/expdesign/zltexp.py | 30 ++++++++++++++++++++---------- npf/sections/__init__.py | 16 ++++++++++------ 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/integration/zlt.npf b/integration/zlt.npf index 93641aa..65a76a6 100644 --- a/integration/zlt.npf +++ b/integration/zlt.npf @@ -17,5 +17,7 @@ else fi t=$(echo "$RATE*(100-$d)/100" | bc) +p=$(echo "$t * 100 / $RATE" | bc) echo "RESULT-DROPPEDPC $d" +echo "RESULT-GOODPC $p" echo "RESULT-THROUGHPUT $t" diff --git a/npf/expdesign/zltexp.py b/npf/expdesign/zltexp.py index e0ec68f..1bb19f4 100644 --- a/npf/expdesign/zltexp.py +++ b/npf/expdesign/zltexp.py @@ -7,27 +7,26 @@ from npf.types.dataset import Run from npf.variable import Variable - -class ZLTVariableExpander(FullVariableExpander): - - def __init__(self, vlist:Dict[str,Variable], results, overriden, input, output, margin, all=False): - - +class OptVariableExpander(FullVariableExpander): + def __init__(self, vlist:Dict[str,Variable], results, overriden, input, margin, all=False): if not input in vlist: raise Exception(f"{input} is not in the variables, please define a variable in the %variable section.") + self.results = results self.input = input self.input_values = vlist[input].makeValues() + if len(self.input_values) <= 2: + print(f"WARNING: Doing zero-loss-throughput search on the variable {input} that has only {len(self.input_values)} values. This is useless." + f"You must define a range to search with a variable like {input}=[0-100#5].") del vlist[input] self.current = None - self.output = output self.n_done = 0 self.n_it = 0 self.n_tot_done = 0 self.margin = margin self.all = all super().__init__(vlist, overriden) - + def __iter__(self): self.it = self.expanded.__iter__() self.current = None @@ -38,6 +37,15 @@ def __iter__(self): def __len__(self): return int(len(self.expanded) * ceil(log2(len(self.input_values)) if (self.n_it <= 1) else self.n_tot_done/(self.n_it - 1))) +class ZLTVariableExpander(OptVariableExpander): + + def __init__(self, vlist:Dict[str,Variable], results, overriden, input, output, margin, all=False, perc=False): + + self.output = output + self.perc = perc + super().__init__(vlist, results, overriden, input, margin, all) + + def __next__(self): if self.current == None: @@ -57,6 +65,8 @@ def __next__(self): if self.output: r_out = np.mean(vals[self.output]) r_in = r.variables[self.input] + if self.perc: + r_out = r_out/100 * r_in vals_for_current[r_in] = r_out if r_out >= r_in/self.margin: acceptable_rates.append(r_in) @@ -65,7 +75,7 @@ def __next__(self): except KeyError: raise Exception(f"{self.output} is not in the results. Sample of last result : {vals}") - #Step 1 : try the max output + #Step 1 : try the max input rate first if len(vals_for_current) == 0: next_val = max_r elif len(vals_for_current) == 1: @@ -75,7 +85,7 @@ def __next__(self): self.current = None return self.__next__() - #Step 2 : go for the rate below the max output + #Step 2 : go for the rate below the output of the max input maybe_achievable_inputs = list(filter(lambda x : x <= max_r, self.input_values)) next_val = max(maybe_achievable_inputs) else: diff --git a/npf/sections/__init__.py b/npf/sections/__init__.py index 5b69544..b5a33f7 100644 --- a/npf/sections/__init__.py +++ b/npf/sections/__init__.py @@ -203,12 +203,16 @@ def replace_all(self, value): def expand(self, results={}, method="full", overriden=set()): if method == "shuffle" or method == "rand" or method == "random": return RandomVariableExpander(self.vlist) - elif method.lower().startswith("zlt"): - params = method[4:-1].split(",") - return ZLTVariableExpander(self.vlist, overriden=overriden, results=results, input=params[0], output=params[1], margin=1.01 if len(params) == 2 else float(params[2])) - elif method.lower().startswith("allzlt"): - params = method[7:-1].split(",") - return ZLTVariableExpander(self.vlist, overriden=overriden, results=results, input=params[0], output=params[1], margin=1.01 if len(params) == 2 else float(params[2]), all=True) + elif "zl" in method.lower(): + if method.lower().startswith("allzl"): + params = method[7:-1].split(",") + all = True + perc = method.lower()[5] == 'p' + else: + params = method[4:-1].split(",") + all = False + perc = method.lower()[2] == 'p' + return ZLTVariableExpander(self.vlist, overriden=overriden, results=results, input=params[0], output=params[1], margin=1.01 if len(params) == 2 else float(params[2]), all=all, perc=perc) else: return FullVariableExpander(self.vlist, overriden)