Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(183)

Unified Diff: swarm_client/utils/short_expression_finder.py

Issue 69143004: Delete swarm_client. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « swarm_client/utils/net.py ('k') | swarm_client/utils/threading_utils.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: swarm_client/utils/short_expression_finder.py
===================================================================
--- swarm_client/utils/short_expression_finder.py (revision 235167)
+++ swarm_client/utils/short_expression_finder.py (working copy)
@@ -1,176 +0,0 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Generates short, hopefully readable Python expressions that test variables
-for certain combinations of values.
-"""
-
-import itertools
-import re
-
-
-class ShortExpressionFinder(object):
- """Usage:
- >>> sef = ShortExpressionFinder([('foo', ("a", "b", "c", "d")),
- ... ('bar', (1, 2))])
- >>> sef.get_expr([("a", 1)])
- foo=="a" and bar==1
- >>> sef.get_expr([("a", 1), ("b", 2), ("c", 1)])
- ((foo=="a" or foo=="c") and bar==1) or (foo=="b" and bar==2)
-
- The returned expressions are of the form
- EXPR ::= EXPR2 ( "or" EXPR2 )*
- EXPR2 ::= EXPR3 ( "and" EXPR3 )*
- EXPR3 ::= VAR "==" VALUE ( "or" VAR "==" VALUE )*
- where all of the comparisons in an EXPR2 involve the same variable.
- Only positive tests are used so that all expressions will evaluate false if
- given an unanticipated combination of values.
-
- A "cheapest" expression is returned. The cost of an expression is a function
- of the number of var==value comparisons and the number of parentheses.
-
- The expression is found by exhaustive search, but it seems to be adequately
- fast even for fairly large sets of configuration variables.
- """
-
- # These must be positive integers.
- COMPARISON_COST = 1
- PAREN_COST = 1
-
- def __init__(self, variables_and_values):
- assert variables_and_values
- for k, vs in variables_and_values:
- assert re.match(r'\w+\Z', k)
- assert vs
- assert (all(isinstance(v, int) for v in vs) or
- all(re.match(r'\w+\Z', v) for v in vs))
-
- variables, values = zip(*((k, sorted(v)) for k, v in variables_and_values))
- valuecounts = map(len, values)
- base_tests_by_cost = {}
-
- # Loop over nonempty subsets of values of each variable. This is about 2^n
- # cases where n is the total number of values (currently 2+3=5 in Chrome).
- for subsets in itertools.product(*(range(1, 1 << n) for n in valuecounts)):
- # Supposing values == [['a', 'b', 'c'], [1, 2]], there are six
- # configurations: ('a', 1), ('a', 2), ('b', 1), etc. Each gets a bit, in
- # that order starting from the LSB. Start with the equivalent of
- # set([('a', 1)]) and massage that into the correct set of configs.
- bits = 1
- shift = 1
- cost = 0
- for subset, valuecount in zip(subsets, valuecounts):
- oldbits, bits = bits, 0
- while subset:
- if subset & 1:
- bits |= oldbits
- cost += self.COMPARISON_COST
- oldbits <<= shift
- subset >>= 1
- shift *= valuecount
- # Charge an extra set of parens for the whole expression,
- # which is removed later if appropriate.
- cost += self.PAREN_COST * (1 + sum(bool(n & (n-1)) for n in subsets))
- base_tests_by_cost.setdefault(cost, {})[bits] = subsets
-
- self.variables = variables
- self.values = values
- self.base_tests_by_cost = base_tests_by_cost
-
- def get_expr(self, configs):
- assert configs
- for config in configs:
- assert len(config) == len(self.values)
- assert all(val in vals for val, vals in zip(config, self.values))
- return self._format_expr(self._get_expr_internal(configs))
-
- def _get_expr_internal(self, configs):
- bits = 0
- for config in configs:
- bit = 1
- n = 1
- for value, values in zip(config, self.values):
- bit <<= (n * values.index(value))
- n *= len(values)
- bits |= bit
- notbits = ~bits
-
- def try_partitions(parts, bits):
- for cost, subparts in parts:
- if cost is None:
- return None if bits else ()
- try:
- tests = self.base_tests_by_cost[cost]
- except KeyError:
- continue
- for test in tests:
- if (test & bits) and not (test & notbits):
- result = try_partitions(subparts, bits & ~test)
- if result is not None:
- return (tests[test],) + result
- return None
-
- for total_cost in itertools.count(0):
- try:
- return (self.base_tests_by_cost[total_cost + self.PAREN_COST][bits],)
- except KeyError:
- result = try_partitions(tuple(partitions(total_cost, self.PAREN_COST)),
- bits)
- if result is not None:
- return result
-
- def _format_expr(self, expr):
- out = []
- for expr2 in expr:
- out2 = []
- for name, values, expr3 in zip(self.variables, self.values, expr2):
- out3 = []
- for value in values:
- if expr3 & 1:
- if isinstance(value, basestring):
- value = '"%s"' % value
- out3.append('%s==%s' % (name, value))
- expr3 >>= 1
- out2.append(' or '.join(out3))
- if len(out3) > 1 and len(expr2) > 1:
- out2[-1] = '(%s)' % out2[-1]
- out.append(' and '.join(out2))
- if len(out2) > 1 and len(expr) > 1:
- out[-1] = '(%s)' % out[-1]
- return ' or '.join(out)
-
-
-def partitions(n, minimum):
- """Yields all the ways of expressing n as a sum of integers >= minimum,
- in a slightly odd tree format. Most of the tree is left unevaluated.
- Example:
- partitions(4, 1) ==>
- [1, <[1, <[1, <[1, <end>]>],
- [2, <end>]>],
- [3, <end>]>],
- [2, <[2, <end>]>],
- [4, <end>]
- where <...> is a lazily-evaluated list and end == [None, None].
- """
- if n == 0:
- yield (None, None)
- for k in range(n, minimum - 1, -1):
- children = partitions(n - k, k)
- # We could just yield [k, children] here, but that would create a lot of
- # blind alleys with no actual partitions.
- try:
- yield [k, MemoizedIterable(itertools.chain([next(children)], children))]
- except StopIteration:
- pass
-
-
-class MemoizedIterable(object):
- """Wrapper for an iterable that fully evaluates and caches the values the
- first time it is iterated over.
- """
- def __init__(self, iterable):
- self.iterable = iterable
- def __iter__(self):
- self.iterable = tuple(self.iterable)
- return iter(self.iterable)
« no previous file with comments | « swarm_client/utils/net.py ('k') | swarm_client/utils/threading_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698