예제 #1
0
    def __init__(self,
                 parent=None,
                 name='',
                 lower_left=(0, 0),
                 upper_right=(1, 1)):
        self.parent = parent
        self.name = name
        sn = self.name + '_'
        if parent is None:
            self.solver = kiwi.Solver()
        else:
            self.solver = parent.solver
        self.top = Variable(sn + 'top')
        self.bottom = Variable(sn + 'bottom')
        self.left = Variable(sn + 'left')
        self.right = Variable(sn + 'right')

        self.width = Variable(sn + 'width')
        self.height = Variable(sn + 'height')
        self.h_center = Variable(sn + 'h_center')
        self.v_center = Variable(sn + 'v_center')

        self.min_width = Variable(sn + 'min_width')
        self.min_height = Variable(sn + 'min_height')
        self.pref_width = Variable(sn + 'pref_width')
        self.pref_height = Variable(sn + 'pref_height')

        right, top = upper_right
        left, bottom = lower_left
        self.add_constraints()
예제 #2
0
def solve_ordering(nodes):
    """ Solve for the desired order of the list of nodes.

    This function is an implementation detail and should not be
    consumed by code outside of this module.

    Parameters
    ----------
    nodes : list
        The list of PathNode objects which should be ordered. It
        is assumed that all nodes reside in the same group.

    Returns
    -------
    result : list
        The PathNode objects ordered according to the constraints
        specified by the 'before' and 'after' items attributes.

    """
    variables = {}
    for node in nodes:
        variables[node.id] = kiwi.Variable(str(node.id))

    prev_var = None
    constraints = []
    for node in nodes:
        this_var = variables[node.id]
        constraints.append(this_var >= 0)
        if prev_var is not None:  # weakly preserve relative order
            constraints.append((prev_var + 0.1 <= this_var) | 'weak')
        before = node.item.before
        if before:
            if before not in variables:
                msg = "item '%s' has invalid `before` reference '%s'"
                raise ValueError(msg % (node.path, before))
            target_var = variables[before]
            constraints.append((this_var + 0.1 <= target_var) | 'strong')
        after = node.item.after
        if after:
            if after not in variables:
                msg = "item '%s' has invalid `after` reference '%s'"
                raise ValueError(msg % (node.path, after))
            target_var = variables[after]
            constraints.append((target_var + 0.1 <= this_var) | 'strong')
        prev_var = this_var

    solver = kiwi.Solver()
    for cn in constraints:
        solver.addConstraint(cn)
    solver.updateVariables()

    flat = []
    for node in nodes:
        node_var = variables[node.id]
        flat.append((node_var.value(), node))
    flat.sort()

    return [pair[1] for pair in flat]
예제 #3
0
    def test(self):
        # Setup constrain programming variables.
        fig_w = ks.Variable('figure-width')
        fig_h = ks.Variable('figure-height')
        p1_w = ks.Variable('panel1-width')
        p1_h = ks.Variable('panel1-height')
        p2_w = ks.Variable('panel2-width')
        p2_h = ks.Variable('panel2-height')
        p2a_w = ks.Variable('panel2a-width')
        p2a_h = ks.Variable('panel2a-height')
        p2b_w = ks.Variable('panel2b-width')
        p2b_h = ks.Variable('panel2b-height')
        padding = ks.Variable('padding')

        # Setup solver.
        s = ks.Solver()

        # Setup constraints.
        c1 = fig_w - p1_w == 0
        c2 = fig_w - p2_w == 0
        c3 = p2_w - p2a_w - padding - p2b_w == 0
        c4 = p2a_w - p2b_w == 0
        c5 = fig_h - p1_h - padding - p2_h == 0
        c6 = p2a_h == p2_h
        c7 = p2b_h == p2_h
        c8 = padding == 1.0
        c9 = p1_w == 20.0
        c10 = p1_h == 5.0
        c11 = p2_h == 10.0

        s.addConstraint(c1 | 'strong')
        s.addConstraint(c2 | 'strong')
        s.addConstraint(c3 | 'strong')
        s.addConstraint(c4 | 'strong')
        s.addConstraint(c5 | 'strong')
        s.addConstraint(c6 | 'strong')
        s.addConstraint(c7 | 'strong')
        s.addConstraint(c8 | 'strong')
        s.addConstraint(c9 | 'strong')
        s.addConstraint(c10 | 'strong')
        s.addConstraint(c11 | 'strong')

        s.updateVariables()

        # Check results
        self.assertEqual(fig_w.value(), 20)
        self.assertEqual(fig_h.value(), 16)
        self.assertEqual(p1_w.value(), 20)
        self.assertEqual(p1_h.value(), 5)
        self.assertEqual(p2_w.value(), 20)
        self.assertEqual(p2_h.value(), 10)
        self.assertEqual(p2a_w.value(), 9.5)
        self.assertEqual(p2a_h.value(), 10)
        self.assertEqual(p2b_w.value(), 9.5)
        self.assertEqual(p2b_h.value(), 10)
        self.assertEqual(padding.value(), 1.0)
예제 #4
0
    def __init__(self,
                 parent=None,
                 name='',
                 tight=False,
                 artist=None,
                 lower_left=(0, 0),
                 upper_right=(1, 1),
                 spine=False):
        Variable = kiwi.Variable
        self.parent = parent
        self.name = name
        sn = self.name + '_'
        if parent is None:
            self.solver = kiwi.Solver()
        else:
            self.solver = parent.solver
            parent.add_child(self)
        # keep track of artist associated w/ this layout.  Can be none
        self.artist = artist
        # keep track if this box is supposed to be a spine that is constrained by the parent.
        self.spine = spine

        self.top = Variable(sn + 'top')
        self.bottom = Variable(sn + 'bottom')
        self.left = Variable(sn + 'left')
        self.right = Variable(sn + 'right')

        self.width = Variable(sn + 'width')
        self.height = Variable(sn + 'height')
        self.h_center = Variable(sn + 'h_center')
        self.v_center = Variable(sn + 'v_center')

        self.min_width = Variable(sn + 'min_width')
        self.min_height = Variable(sn + 'min_height')
        self.pref_width = Variable(sn + 'pref_width')
        self.pref_height = Variable(sn + 'pref_height')

        right, top = upper_right
        left, bottom = lower_left
        self.tight = tight
        self.add_constraints()
        self.children = []
        self.subplotspec = None
예제 #5
0
def evaluate_constraints(view: IView[NT], top_rect: Rect[sym.Rational], constraints: List[IConstraint],
                         strength: str = 'strong') -> IView[sym.Float]:
    solver = kiwisolver.Solver()
    env = make_kiwi_env([v for v in view])

    add_linear_axioms(solver, [v for v in view], env)
    for constr in constraints:
        solver.addConstraint(constraint_to_kiwi(constr, env, strength=strength))

    t_x, t_y = kiwi_lookup(view.left_anchor, env), kiwi_lookup(view.top_anchor, env)
    t_b, t_r = kiwi_lookup(view.bottom_anchor, env), kiwi_lookup(view.right_anchor, env)

    c_x, c_y, c_r, c_b = (top_rect.left, top_rect.top, top_rect.right, top_rect.bottom)

    solver.addConstraint((t_x == float(c_x)) | strength)
    solver.addConstraint((t_y == float(c_y)) | strength)
    solver.addConstraint((t_b == float(c_b)) | strength)
    solver.addConstraint((t_r == float(c_r)) | strength)

    solver.updateVariables()

    def get(anchor: IAnchor[NT]) -> float:
        kv = kiwi_lookup(anchor, env)
        return cast(float, kv.value())

    def recurse(seed: IView[NT]) -> IViewBuilder:
        l, t = seed.left_anchor, seed.top_anchor
        r, b = seed.right_anchor, seed.bottom_anchor

        # left top right bottom
        rect = (get(l), get(t), get(r), get(b))

        children = [recurse(inner) for inner in seed.children]

        return V(name=seed.name, rect=rect, children=children)

    return recurse(view).build(number_type=sym.Float)
 def __init__(self):
     self._solver = kiwi.Solver()
     self._edit_stack = []
     self._initialized = False
     self._running = False
예제 #7
0
    def __init__(self, parent=None, name='', tightwidth=False,
                 tightheight=False, artist=None,
                 lower_left=(0, 0), upper_right=(1, 1), pos=False,
                 subplot=False, h_pad=None, w_pad=None):
        Variable = kiwi.Variable
        self.parent = parent
        self.name = name
        sn = self.name + '_'
        if parent is None:
            self.solver = kiwi.Solver()
            self.constrained_layout_called = 0
        else:
            self.solver = parent.solver
            self.constrained_layout_called = None
            # parent wants to know about this child!
            parent.add_child(self)
        # keep track of artist associated w/ this layout.  Can be none
        self.artist = artist
        # keep track if this box is supposed to be a pos that is constrained
        # by the parent.
        self.pos = pos
        # keep track of whether we need to match this subplot up with others.
        self.subplot = subplot

        # we need the str below for Py 2 which complains the string is unicode
        self.top = Variable(str(sn + 'top'))
        self.bottom = Variable(str(sn + 'bottom'))
        self.left = Variable(str(sn + 'left'))
        self.right = Variable(str(sn + 'right'))

        self.width = Variable(str(sn + 'width'))
        self.height = Variable(str(sn + 'height'))
        self.h_center = Variable(str(sn + 'h_center'))
        self.v_center = Variable(str(sn + 'v_center'))

        self.min_width = Variable(str(sn + 'min_width'))
        self.min_height = Variable(str(sn + 'min_height'))
        self.pref_width = Variable(str(sn + 'pref_width'))
        self.pref_height = Variable(str(sn + 'pref_height'))
        # margis are only used for axes-position layout boxes.  maybe should
        # be a separate subclass:
        self.left_margin = Variable(str(sn + 'left_margin'))
        self.right_margin = Variable(str(sn + 'right_margin'))
        self.bottom_margin = Variable(str(sn + 'bottom_margin'))
        self.top_margin = Variable(str(sn + 'top_margin'))
        # mins
        self.left_margin_min = Variable(str(sn + 'left_margin_min'))
        self.right_margin_min = Variable(str(sn + 'right_margin_min'))
        self.bottom_margin_min = Variable(str(sn + 'bottom_margin_min'))
        self.top_margin_min = Variable(str(sn + 'top_margin_min'))

        right, top = upper_right
        left, bottom = lower_left
        self.tightheight = tightheight
        self.tightwidth = tightwidth
        self.add_constraints()
        self.children = []
        self.subplotspec = None
        if self.pos:
            self.constrain_margins()
        self.h_pad = h_pad
        self.w_pad = w_pad
예제 #8
0
 def __init__(self, joints, layers):
     self.joints = joints
     self.layers = layers
     self.solver = kiwisolver.Solver()
     self.variables = {}
예제 #9
0
    def __init__(self,
                 parent=None,
                 parent_pos=(0, 0),
                 parent_inner=False,
                 name='',
                 ncols=1,
                 nrows=1,
                 h_pad=None,
                 w_pad=None,
                 width_ratios=None,
                 height_ratios=None):
        Variable = kiwi.Variable
        self.parent = parent
        self.parent_pos = parent_pos
        self.parent_inner = parent_inner
        self.name = name
        self.nrows = nrows
        self.ncols = ncols
        self.height_ratios = np.atleast_1d(height_ratios)
        if height_ratios is None:
            self.height_ratios = np.ones(nrows)
        self.width_ratios = np.atleast_1d(width_ratios)
        if width_ratios is None:
            self.width_ratios = np.ones(ncols)

        sn = self.name + '_'
        if parent is None:
            self.parent = None
            self.solver = kiwi.Solver()
        else:
            self.parent = parent
            parent.add_child(self, *parent_pos)
            self.solver = self.parent.solver
        # keep track of artist associated w/ this layout.  Can be none
        self.artists = np.empty((nrows, ncols), dtype=object)
        self.children = np.empty((nrows, ncols), dtype=object)

        self.margins = {}
        self.margin_vals = {}
        # all the boxes in each column share the same left/right margins:
        for todo in ['left', 'right', 'leftcb', 'rightcb']:
            # track the value so we can change only if a margin is larger
            # than the current value
            self.margin_vals[todo] = np.zeros(ncols)

        sol = self.solver

        # These are redundant, but make life easier if
        # we define them all.  All that is really
        # needed is left/right, margin['left'], and margin['right']
        self.widths = [Variable(f'{sn}widths[{i}]') for i in range(ncols)]
        self.lefts = [Variable(f'{sn}lefts[{i}]') for i in range(ncols)]
        self.rights = [Variable(f'{sn}rights[{i}]') for i in range(ncols)]
        self.inner_widths = [
            Variable(f'{sn}inner_widths[{i}]') for i in range(ncols)
        ]
        for todo in ['left', 'right', 'leftcb', 'rightcb']:
            self.margins[todo] = [
                Variable(f'{sn}margins[{todo}][{i}]') for i in range(ncols)
            ]
            for i in range(ncols):
                sol.addEditVariable(self.margins[todo][i], 'strong')

        for todo in ['bottom', 'top', 'bottomcb', 'topcb']:
            self.margins[todo] = np.empty((nrows), dtype=object)
            self.margin_vals[todo] = np.zeros(nrows)

        self.heights = [Variable(f'{sn}heights[{i}]') for i in range(nrows)]
        self.inner_heights = [
            Variable(f'{sn}inner_heights[{i}]') for i in range(nrows)
        ]
        self.bottoms = [Variable(f'{sn}bottoms[{i}]') for i in range(nrows)]
        self.tops = [Variable(f'{sn}tops[{i}]') for i in range(nrows)]
        for todo in ['bottom', 'top', 'bottomcb', 'topcb']:
            self.margins[todo] = [
                Variable(f'{sn}margins[{todo}][{i}]') for i in range(nrows)
            ]
            for i in range(nrows):
                sol.addEditVariable(self.margins[todo][i], 'strong')

        # set these margins to zero by default. They will be edited as
        # children are filled.
        self.reset_margins()
        self.add_constraints()

        self.h_pad = h_pad
        self.w_pad = w_pad
예제 #10
0
# 0|-------------| x1 ----- xm ----- x2 |-----------------------|100
x1 = kiwi.Variable('x1')
x2 = kiwi.Variable('x2')
xm = kiwi.Variable('xm')
sm = kiwi.Variable('sm')
sm2 = kiwi.Variable('sm')

constraints = [
    x1 >= 0,
    x2 <= 100,
    x2 >= x1 + 10,
    xm == (x1 + x2) / 2,
    sm == x1 + x2,
]  # these all have strength 'required'

solver = kiwi.Solver()
for cn in constraints:
    solver.addConstraint(cn)

solver.addEditVariable(xm, 'strong')
solver.addEditVariable(sm, 'weak')

solver.addConstraint(sm >= 100)
solver.suggestValue(xm, 40)
solver.updateVariables()
print('x1:', x1.value())
print('x2:', x2.value())
print('xm:', xm.value())
print('sm:', sm.value())
예제 #11
0
	def __init__(self, figwidth=Fixed(0.0), figheight=Fixed(0.0),
					margin_left=0.0, margin_right=0.0,
					margin_top=0.0, margin_bottom=0.0,
					layout='vertical', padding=0.0):
		"""Default constructor.

		Args:
		:param figwidth: Width of the figure, base size is adjusted re: margins.
		:param figheight: Height of the figure, base is adjusted re: margins.
		:param margin_left float: Width of the margin on the left-hand side [cm].
		:param margin_right float: Width of the margin on the right-hand side [cm].
		:param margin_top float: Height of the margin at the top of the plot [cm].
		:param margin_bottom float: Height of the margin at the bottom of the plot [cm].
		:param layout str: Is the figure layed out with each element horizontally ('horizontal') or vertically ('vertical').
		:param padding float: How much padding is there between elements [cm].
		"""

		self.store = dict()

		self.solver = ks.Solver()

		self.label_index = 0

		self.fig_width_constraint = figwidth
		self.fig_height_constraint = figheight

		# All the plot elements are arranged in a tree structure, built
		# from a linked list of PlotElement objects. Base is the root of
		# this tree.
		self.base = PlotElement()
		self.base.label = 'base'
		self.base.width.setName('base-w')
		self.base.height.setName('base-h')
		self.parent = None

		# Set base plot element parameters.
		if isinstance(figwidth, Fixed):
			self.solver.addConstraint((self.base.width == figwidth.size -
									margin_left - margin_right) | 'required')
		elif isinstance(figwidth, FromChildren):
			pass
		elif isinstance(figwidth, Named):
			pass
		else:
			raise InappropriateConstraint(type(figwidth),'base','Figure width setup can only be \
						constrained using Fixed, FromChildren or Named.')
		self.base.width_constraint = figwidth

		if isinstance(figheight, Fixed):
			self.solver.addConstraint((self.base.height == figheight.size -
									margin_bottom - margin_top) | 'required')
		elif isinstance(figheight, FromChildren):
			pass
		elif isinstance(figheight, Named):
			pass
		else:
			raise InappropriateConstraint(type(figheight),'base','Figure height setup can only be \
						constrained using Fixed, FromChildren or Named.')
		self.base.height_constraint = figheight

		self.base.margin_left = margin_left
		self.base.margin_right = margin_right
		self.base.margin_top = margin_top
		self.base.margin_bottom = margin_bottom
		self.base.padding = padding
		if layout=='horizontal':
			self.base.layout = 'horizontal'
		elif layout=='vertical':
			self.base.layout = 'vertical'
		else:
			raise ValueError('Unknown layout method <{}> (should be horizontal or vertical)'.format(layout))

		# Initialise the dictionary (we are subclassing the dict class).
		self.store['base'] = self.base

		# Store the full figure dimensions - although this won't be determined until we
		# complete the layout.
		self.figure_width = 0.0
		self.figure_height = 0.0
예제 #12
0
파일: hyperbolic.py 프로젝트: aji/garage
import sys
import time
import math
import os

import kiwisolver as K

import pygame
from pygame.locals import *

from py.util.math import lerp_unlerp

solver = K.Solver()

width = K.Variable("width")
height = K.Variable("height")
pad = K.Variable("pad")

plots_x = K.Variable("plots_x")
plots_y = K.Variable("plots_y")
plot_sz = K.Variable("plot_sz")

solver.addEditVariable(width, "strong")
solver.addEditVariable(height, "strong")
solver.addEditVariable(pad, "strong")

solver.addConstraint(pad <= plots_x)
solver.addConstraint(pad <= plots_y)
solver.addConstraint(plots_x + plot_sz + pad + plot_sz + plots_x == width)
solver.addConstraint(plots_y + plot_sz + plots_y == height)