python:intvectorrange
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| python:intvectorrange [2010/10/29 11:52] – tkbletsc | python:intvectorrange [2012/09/25 13:04] (current) – tkbletsc | ||
|---|---|---|---|
| Line 12: | Line 12: | ||
| # if only one argument is given to __init__, then the range goes from [0,0,...,0] to the vector given | # if only one argument is given to __init__, then the range goes from [0,0,...,0] to the vector given | ||
| class IntVectorRange(object): | class IntVectorRange(object): | ||
| - | def __init__(self, | + | |
| - | if end is None: | + | if end is None: |
| - | end=start | + | end=start |
| - | start=[0] * len(end) | + | start=[0] * len(end) |
| - | self.start=start | + | |
| - | self.end=end | + | self.end=end |
| - | self.size = len(start) | + | self.size = len(start) |
| - | self.delta = [end[i]-start[i]+1 | + | self.delta = [end[i]-start[i]+1 |
| - | self.len = reduce(lambda x,y: x*y, self.delta, 1) | + | self.len = reduce(lambda x,y: x*y, self.delta, 1) |
| - | def __getitem__(self, | + | |
| - | if index >= self.len: raise IndexError | + | if index >= self.len: raise IndexError |
| - | r = [0] * self.size | + | r = [0] * self.size |
| - | for i in xrange(self.size): | + | for i in xrange(self.size): |
| - | r[i] = index % self.delta[i] + self.start[i] | + | r[i] = index % self.delta[i] + self.start[i] |
| - | index /= self.delta[i] | + | index /= self.delta[i] |
| - | return r | + | return r |
| - | def __len__(self): | + | |
| - | + | ||
| - | # provides | + | # Provides |
| # (based on a binary IntVectorRange object) | # (based on a binary IntVectorRange object) | ||
| # | # | ||
| - | # Example: | + | # Example: |
| # [] | # [] | ||
| # | # | ||
| Line 45: | Line 45: | ||
| # | # | ||
| # | # | ||
| - | class AllCombinations: | + | class AllSubsets: |
| - | def __init__(self, | + | def __init__(self, |
| - | self.vector_range = IntVectorRange([1] * len(items)) | + | self.vector_range = IntVectorRange([1] * len(items)) |
| - | self.items = items | + | self.items = items |
| - | + | ||
| - | def __getitem__(self, | + | def __getitem__(self, |
| - | v = self.vector_range[index] | + | v = self.vector_range[index] |
| - | return [self.items[i] for i in xrange(len(v)) if v[i]] | + | return [self.items[i] for i in xrange(len(v)) if v[i]] |
| - | + | ||
| - | def __len__(self): | + | def __len__(self): |
| # for academic purposes only, here's the same class based on inheritence instead of composition | # for academic purposes only, here's the same class based on inheritence instead of composition | ||
| - | class AllCombinations2(IntVectorRange): | + | class AllSubsets2(IntVectorRange): |
| def __init__(self, | def __init__(self, | ||
| super(AllCombinations2, | super(AllCombinations2, | ||
| Line 66: | Line 66: | ||
| return [self.items[i] for i in xrange(len(v)) if v[i]] | return [self.items[i] for i in xrange(len(v)) if v[i]] | ||
| + | |||
| + | # Provides a list with all possible " | ||
| + | # | ||
| + | # Example: AllCombinations([" | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | # | ||
| + | class AllCombinations: | ||
| + | def __init__(self, | ||
| + | self.vector_range = IntVectorRange([len(choice)-1 for choice in choices]) | ||
| + | self.choices = choices | ||
| + | |||
| + | def __getitem__(self, | ||
| + | c_indices = self.vector_range[index] | ||
| + | return [self.choices[i][c_indices[i]] for i in xrange(len(self.choices))] | ||
| + | |||
| + | def __len__(self): | ||
| </ | </ | ||
| + | |||
| + | This can be used to build a simple combinatorial optimizer: | ||
| + | < | ||
| + | import operator | ||
| + | |||
| + | # Optimize the return value of the given function func(), comparing return values with the is_this_better() function (which defaults to greater-than). | ||
| + | # All parameters must be named parameters, and come after all other arguments. Options: | ||
| + | # - Print out the latest best answer if print_on_better is True | ||
| + | # - If return_choices_only is True, then the best_inputs part of the return will only have the choices, not the fixed values | ||
| + | # Returns the tuple: (best_inputs, | ||
| + | # | ||
| + | # Example: | ||
| + | # def f(x,y,z): return x**2+x+5-y**3+z | ||
| + | # print optimize(f, x=Choice(range(-3, | ||
| + | # | ||
| + | # This finds the best x and y to maximize f(x,y,z) with the given choices, with z fixed at 2. | ||
| + | class Choice(list): | ||
| + | def optimize(func, | ||
| + | choices = {} | ||
| + | fixed_values = {} | ||
| + | for k,v in vargs.items(): | ||
| + | if isinstance(v, | ||
| + | else: fixed_values[k] = v | ||
| + | c_keys = choices.keys() | ||
| + | c_value_choices = [choices[k] for k in c_keys] | ||
| + | |||
| + | best_value = None | ||
| + | best_inputs = None | ||
| + | for c_values in AllCombinations(c_value_choices): | ||
| + | chosen = dict((k, | ||
| + | all_values = chosen.copy() | ||
| + | all_values.update(fixed_values) | ||
| + | value = func(**all_values) | ||
| + | if best_value is None or is_this_better(value, | ||
| + | best_inputs = chosen if return_choices_only else all_values | ||
| + | best_value = value | ||
| + | if print_on_better: | ||
| + | return (best_inputs, | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
python/intvectorrange.1288378375.txt.gz · Last modified: by tkbletsc
