Feature Request: Weighted Or (already have implementation to use)
docfate111 opened this issue · 4 comments
Is your feature request related to a problem? Please describe
A request for Or() but with weights
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Or() equally gives each option the same probability.
Describe the solution you'd like
Each statement in the Or is in a tuple of which the first is the option the or chooses and second is the probability that the option is taken.
A clear and concise description of what you want to happen.
Describe alternatives you've considered
class WeightedOr(Field):
"""A ``Field`` subclass that chooses one of the provided values at
random as the result of a call to the ``build()`` method. Takes an
odds array rather than just direct values."""
def __init__(self, *values, **kwargs):
'''
values is a list of tuples
'''
self.shortest_vals = None
vals=[x[0] for x in values]
self.values= list(map(maybe_binstr, vals))
self.weights = [x[1] for x in values]
#print(self.weights)
if abs(1.0 - sum(self.weights)) > 0.0001:
raise("Weights in WeightedOr don't sum to 1.0: {}".format(self.weights))
if "options" in kwargs and len(values) == 0:
self.values = list(map(maybe_binstr, kwargs["options"]))
self.rolling = kwargs.setdefault("rolling", False)
def build(self, pre=None, shortest=False):
"""
:param list pre: The prerequisites list
:param bool shortest: Whether or not the shortest reference-chain (most minimal)
version of the field should be generated.
"""
#self.values=list(map(val, self.values))
#self.shortest_vals=list(map(val, self.values))
if pre is None:
pre = []
# self.shortest_vals will be set by the GramFuzzer and will
# contain a list of value options that have a minimal reference chain
if shortest and self.shortest_vals is not None:
return utils.val(random.choices(self.shortest_vals, self.weights)[0], pre, shortest=shortest)
else:
return utils.val(random.choices(self.values, self.weights)[0], pre, shortest=shortest)
A clear and concise description of any alternative solutions or features you've considered.
implementation of solution
Additional context
Add any other context or screenshots about the feature request here.
The code got messed up formatting
The implementation I mean is here:
https://github.com/mgree/smoosh-fuzz/blob/master/weightedOr.py
Thanks for the feature request! I like this idea a lot!
Added as part of v1.4.0:
from collections import defaultdict
from gramfuzz.fields import WeightedOr, WOr
counts = defaultdict(int)
wor = WOr(
("50%", 0.5),
("30%", 0.3),
("20%", 0.2),
)
iters = 100000
for x in range(iters):
val = wor.build()
counts[val] += 1
for k, v in counts.items():
print("{}: {:.03f}%".format(k, (v / iters) * 100))
outputs
b'50%': 50.034%
b'30%': 30.163%
b'20%': 19.803%
Thanks for implementing! I believe there is a bug my code that ran before is not getting ""Weights in WeightedOr don't sum to 1.0" error when it worked before and I checked the values. Also I am unable to run it in Python 3 only in Python 2.7 does it work after running both setup.py in the repo and pip/pip3.