예제 #1
0
파일: solver.py 프로젝트: pombreda/gremlin
class ConstraintSolver(object):
    def __init__(self, root):
        self.root = root
        self.window_width = LinVar("window_width", "input")
        self.window_height = LinVar("window_height", "input")
        self.linsys = LinSys(list(self.root.get_constraints()))
        self.linsys.append(LinEq(self.root.w, self.window_width))
        self.linsys.append(LinEq(self.root.h, self.window_height))
        freeness_relation = ["offset", "cons", "user", None, "padding", "input"]
        var_order = sorted(self.linsys.get_vars(), key = lambda v: freeness_relation.index(v.kind))
        self.solution = self.linsys.solve(var_order)
        for var in self.get_freevars():
            if var.kind == "padding":
                self.solution[var] = 0.0
        self.dependencies = self._calculate_dependencies()
        self.results = {}
        self.watchers = {}

    def __str__(self):
        return "\n".join("%s = %s" % (k, v) for k, v in self.solution.items()
            if not isinstance(v, FreeVar))
    def __getitem__(self, var):
        if var in self.results:
            return self.results[var]
        return self.solution[var]
    def __contains__(self, var):
        return var in self.results or var in self.solution

    def is_free(self, var):
        return isinstance(self.solution[var], FreeVar)
    def get_freevars(self):
        for k, v in self.solution.items():
            if isinstance(v, FreeVar):
                yield k

    def _get_equation_vars(self, expr):
        if isinstance(expr, (str, LinVar, FreeVar)):
            return {expr.name}
        elif isinstance(expr, BinExpr):
            return self._get_equation_vars(expr.lhs) | self._get_equation_vars(expr.rhs)
        else:
            return set()
    def _transitive_closure(self, deps):
        oldlen = -1
        while oldlen != len(deps):
            oldlen = len(deps)
            for resvar, expr in self.solution.items():
                depvars = self._get_equation_vars(expr)
                if deps & depvars:
                    deps.add(resvar)
    def _calculate_dependencies(self):
        dependencies = {}
        for var in self.get_freevars():
            dependencies[var] = {var}
            self._transitive_closure(dependencies[var])
        return dependencies

    def update(self, freevars):
        prev_results = self.results.copy()
        for k in freevars.keys():
            if not self.is_free(k):
                raise ValueError("%r is not a free variable" % (k,))
            for k2 in self.dependencies[k]:
                self.results.pop(k2, NotImplemented)
        
        def rec_eval(key):
            if key in self.results:
                if self.results[key] is NotImplemented:
                    raise ValueError("Cyclic dependency found, var = %r" % (key,))
                return self.results[key]
            # set up sentinel to detect cycles
            self.results[key] = NotImplemented
            v = self.solution[key]
            if isinstance(v, FreeVar):
                if key not in freevars:
                    if key.default is not None:
                        self.results[key] = key.default
                    else:
                        raise ValueError("No value specified for %r" % (key,))
                else:
                    self.results[key] = freevars[key]
            elif hasattr(v, "eval"):
                self.results[key] = v.eval(rec_eval_dict)
            else:
                self.results[key] = v
            return self.results[key]

        rec_eval_dict = RecEvalDict(rec_eval)
        for k in self.solution:
            rec_eval(k)
        
        for k, v in self.results.items():
            prev = prev_results.get(k, NotImplemented)
            if prev != v:
                print "solver: %s=%r" % (k, v)
                for cb in self.watchers.get(k, ()):
                    cb(v)
        
        return self.results
    
    def flash(self, var):
        self.update({var : 1})
        self.update({var : 0})
    def set(self, var, val):
        self.update({var : val})
    
    def watch(self, var, callback):
        if not var in self.watchers:
            self.watchers[var] = []
        self.watchers[var].append(callback)
예제 #2
0
파일: solver.py 프로젝트: pombreda/sadna
class ModelSolver(object):
    def __init__(self, root):
        self.root = root
        self.linsys = LinSys(list(self.root.get_constraints()))
        self._solve_and_eliminate_padding()
        self.dependencies = self._calculate_dependencies()
        self.results = {} #v : v.default for v in self.get_freevars() if v.default is not None}
        self.observed = {}
    
    def __str__(self):
        return "\n".join("%s = %s" % (k, v) for k, v in self.solution.items()
            if not isinstance(v, FreeVar))
    
    def __getitem__(self, var):
        if var in self.results:
            return self.results[var]
        return self.solution[var]

    def __contains__(self, var):
        return var in self.results or var in self.solution

    def _resolve(self):
        freeness_relation = [None, "user", "offset", "cons", "padding", "default", "input"]
        var_order = sorted(self.linsys.get_vars(), key = lambda v: freeness_relation.index(v.type))
        self.solution = self.linsys.solve(var_order)

    def _solve_and_eliminate_padding(self):
        self._resolve()
        for var in self.get_freevars():
            if var.type == "padding":
                self.solution[var] = 0.0
        
        #fixed = set()
        #unfixed = set()
        #for var, val in self.solution.items():
        #    if var.type == "padding":
        #        if isinstance(val, (int, float)):
        #            fixed.add(var)
        #        else:
        #            unfixed.add(var)
        #
        #unfixed -= fixed
        #print "!! unfixed =", unfixed
        #for var in list(unfixed):
        #    try:
        #        self._resolve({var})
        #    except NoSolutionsExist:
        #        unfixed.discard(var)
        #self._resolve(unfixed)

    def get_freevars(self):
        for k, v in self.solution.items():
            if isinstance(v, FreeVar):
                yield k
    
    def _get_equation_vars(self, expr):
        if isinstance(expr, (str, LinVar, FreeVar)):
            return {expr.name}
        elif isinstance(expr, BinExpr):
            return self._get_equation_vars(expr.lhs) | self._get_equation_vars(expr.rhs)
        else:
            return set()
    
    def _transitive_closure(self, deps):
        oldlen = -1
        while oldlen != len(deps):
            oldlen = len(deps)
            for resvar, expr in self.solution.items():
                depvars = self._get_equation_vars(expr)
                if deps & depvars:
                    deps.add(resvar)
    
    def _calculate_dependencies(self):
        dependencies = {}
        for var in self.get_freevars():
            dependencies[var] = {var}
            self._transitive_closure(dependencies[var])
        return dependencies
    
    def update(self, freevars):
        changed = {}
        for k in freevars.keys():
            if not self.is_free(k):
                raise ValueError("%r is not a free variable" % (k,))
            for k2 in self.dependencies[k]:
                v = self.results.pop(k2, NotImplemented)
                if k2 not in changed:
                    changed[k2] = v
        
        def rec_eval(key):
            if key in self.results:
                if self.results[key] is NotImplemented:
                    raise ValueError("cyclic dependency found, var = %r" % (key,))
                return self.results[key]
            # set up sentinel to detect cycles
            self.results[key] = NotImplemented
            v = self.solution[key]
            if isinstance(v, FreeVar):
                if key not in freevars and key.default is not None:
                    self.results[key] = key.default
                else:
                    self.results[key] = freevars[key]
            elif hasattr(v, "eval"):
                self.results[key] = v.eval(rec_eval_dict)
            else:
                self.results[key] = v
            return self.results[key]

        rec_eval_dict = RecEvalDict(rec_eval)
        for k in self.solution:
            rec_eval(k)
        
        for k, oldv in changed.items():
            v = self.results[k]
            if oldv != v and k in self.observed:
                for cb in self.observed[k]:
                    cb(v)
        
        return self.results
    
    def is_free(self, var):
        return isinstance(self.solution[var], FreeVar)
    
    def watch(self, var, callback):
        if var not in self.observed:
            self.observed[var] = []
        self.observed[var].append(callback)
    
    def invoke_observers(self):
        for var, callbacks in self.observed.items():
            if var not in self:
                continue
            val = self[var]
            for cb in callbacks:
                cb(val)
예제 #3
0
class ModelSolver(object):
    def __init__(self, root):
        self.root = root
        self.linsys = LinSys(list(self.root.get_constraints()))
        self._solve_and_eliminate_padding()
        self.dependencies = self._calculate_dependencies()
        self.results = {
        }  #v : v.default for v in self.get_freevars() if v.default is not None}
        self.observed = {}

    def __str__(self):
        return "\n".join("%s = %s" % (k, v) for k, v in self.solution.items()
                         if not isinstance(v, FreeVar))

    def __getitem__(self, var):
        if var in self.results:
            return self.results[var]
        return self.solution[var]

    def __contains__(self, var):
        return var in self.results or var in self.solution

    def _resolve(self):
        freeness_relation = [
            None, "user", "offset", "cons", "padding", "default", "input"
        ]
        var_order = sorted(self.linsys.get_vars(),
                           key=lambda v: freeness_relation.index(v.type))
        self.solution = self.linsys.solve(var_order)

    def _solve_and_eliminate_padding(self):
        self._resolve()
        for var in self.get_freevars():
            if var.type == "padding":
                self.solution[var] = 0.0

        #fixed = set()
        #unfixed = set()
        #for var, val in self.solution.items():
        #    if var.type == "padding":
        #        if isinstance(val, (int, float)):
        #            fixed.add(var)
        #        else:
        #            unfixed.add(var)
        #
        #unfixed -= fixed
        #print "!! unfixed =", unfixed
        #for var in list(unfixed):
        #    try:
        #        self._resolve({var})
        #    except NoSolutionsExist:
        #        unfixed.discard(var)
        #self._resolve(unfixed)

    def get_freevars(self):
        for k, v in self.solution.items():
            if isinstance(v, FreeVar):
                yield k

    def _get_equation_vars(self, expr):
        if isinstance(expr, (str, LinVar, FreeVar)):
            return {expr.name}
        elif isinstance(expr, BinExpr):
            return self._get_equation_vars(expr.lhs) | self._get_equation_vars(
                expr.rhs)
        else:
            return set()

    def _transitive_closure(self, deps):
        oldlen = -1
        while oldlen != len(deps):
            oldlen = len(deps)
            for resvar, expr in self.solution.items():
                depvars = self._get_equation_vars(expr)
                if deps & depvars:
                    deps.add(resvar)

    def _calculate_dependencies(self):
        dependencies = {}
        for var in self.get_freevars():
            dependencies[var] = {var}
            self._transitive_closure(dependencies[var])
        return dependencies

    def update(self, freevars):
        changed = {}
        for k in freevars.keys():
            if not self.is_free(k):
                raise ValueError("%r is not a free variable" % (k, ))
            for k2 in self.dependencies[k]:
                v = self.results.pop(k2, NotImplemented)
                if k2 not in changed:
                    changed[k2] = v

        def rec_eval(key):
            if key in self.results:
                if self.results[key] is NotImplemented:
                    raise ValueError("cyclic dependency found, var = %r" %
                                     (key, ))
                return self.results[key]
            # set up sentinel to detect cycles
            self.results[key] = NotImplemented
            v = self.solution[key]
            if isinstance(v, FreeVar):
                if key not in freevars and key.default is not None:
                    self.results[key] = key.default
                else:
                    self.results[key] = freevars[key]
            elif hasattr(v, "eval"):
                self.results[key] = v.eval(rec_eval_dict)
            else:
                self.results[key] = v
            return self.results[key]

        rec_eval_dict = RecEvalDict(rec_eval)
        for k in self.solution:
            rec_eval(k)

        for k, oldv in changed.items():
            v = self.results[k]
            if oldv != v and k in self.observed:
                for cb in self.observed[k]:
                    cb(v)

        return self.results

    def is_free(self, var):
        return isinstance(self.solution[var], FreeVar)

    def watch(self, var, callback):
        if var not in self.observed:
            self.observed[var] = []
        self.observed[var].append(callback)

    def invoke_observers(self):
        for var, callbacks in self.observed.items():
            if var not in self:
                continue
            val = self[var]
            for cb in callbacks:
                cb(val)
예제 #4
0
class ConstraintSolver(object):
    def __init__(self, root):
        self.root = root
        self.window_width = LinVar("window_width", "input")
        self.window_height = LinVar("window_height", "input")
        self.linsys = LinSys(list(self.root.get_constraints()))
        self.linsys.append(LinEq(self.root.w, self.window_width))
        self.linsys.append(LinEq(self.root.h, self.window_height))
        freeness_relation = [
            "offset", "cons", "user", None, "padding", "input"
        ]
        var_order = sorted(self.linsys.get_vars(),
                           key=lambda v: freeness_relation.index(v.kind))
        self.solution = self.linsys.solve(var_order)
        for var in self.get_freevars():
            if var.kind == "padding":
                self.solution[var] = 0.0
        self.dependencies = self._calculate_dependencies()
        self.results = {}
        self.watchers = {}

    def __str__(self):
        return "\n".join("%s = %s" % (k, v) for k, v in self.solution.items()
                         if not isinstance(v, FreeVar))

    def __getitem__(self, var):
        if var in self.results:
            return self.results[var]
        return self.solution[var]

    def __contains__(self, var):
        return var in self.results or var in self.solution

    def is_free(self, var):
        return isinstance(self.solution[var], FreeVar)

    def get_freevars(self):
        for k, v in self.solution.items():
            if isinstance(v, FreeVar):
                yield k

    def _get_equation_vars(self, expr):
        if isinstance(expr, (str, LinVar, FreeVar)):
            return {expr.name}
        elif isinstance(expr, BinExpr):
            return self._get_equation_vars(expr.lhs) | self._get_equation_vars(
                expr.rhs)
        else:
            return set()

    def _transitive_closure(self, deps):
        oldlen = -1
        while oldlen != len(deps):
            oldlen = len(deps)
            for resvar, expr in self.solution.items():
                depvars = self._get_equation_vars(expr)
                if deps & depvars:
                    deps.add(resvar)

    def _calculate_dependencies(self):
        dependencies = {}
        for var in self.get_freevars():
            dependencies[var] = {var}
            self._transitive_closure(dependencies[var])
        return dependencies

    def update(self, freevars):
        prev_results = self.results.copy()
        for k in freevars.keys():
            if not self.is_free(k):
                raise ValueError("%r is not a free variable" % (k, ))
            for k2 in self.dependencies[k]:
                self.results.pop(k2, NotImplemented)

        def rec_eval(key):
            if key in self.results:
                if self.results[key] is NotImplemented:
                    raise ValueError("Cyclic dependency found, var = %r" %
                                     (key, ))
                return self.results[key]
            # set up sentinel to detect cycles
            self.results[key] = NotImplemented
            v = self.solution[key]
            if isinstance(v, FreeVar):
                if key not in freevars:
                    if key.default is not None:
                        self.results[key] = key.default
                    else:
                        raise ValueError("No value specified for %r" % (key, ))
                else:
                    self.results[key] = freevars[key]
            elif hasattr(v, "eval"):
                self.results[key] = v.eval(rec_eval_dict)
            else:
                self.results[key] = v
            return self.results[key]

        rec_eval_dict = RecEvalDict(rec_eval)
        for k in self.solution:
            rec_eval(k)

        for k, v in self.results.items():
            prev = prev_results.get(k, NotImplemented)
            if prev != v:
                print "solver: %s=%r" % (k, v)
                for cb in self.watchers.get(k, ()):
                    cb(v)

        return self.results

    def flash(self, var):
        self.update({var: 1})
        self.update({var: 0})

    def set(self, var, val):
        self.update({var: val})

    def watch(self, var, callback):
        if not var in self.watchers:
            self.watchers[var] = []
        self.watchers[var].append(callback)