def _pgroup_of_double(polyh, ordered_faces, pgroup): n = len(ordered_faces[0]) # the vertices of the double which sits inside a give polyhedron # can be found by tracking the faces of the outer polyhedron. # A map between face and the vertex of the double is made so that # after rotation the position of the vertices can be located fmap = dict(zip(ordered_faces, range(len(ordered_faces)))) flat_faces = flatten(ordered_faces) new_pgroup = [] for i, p in enumerate(pgroup): h = polyh.copy() h.rotate(p) c = h.corners # reorder corners in the order they should appear when # enumerating the faces reorder = unflatten([c[j] for j in flat_faces], n) # make them canonical reorder = [tuple(map(as_int, minlex(f, directed=False, is_set=True))) for f in reorder] # map face to vertex: the resulting list of vertices are the # permutation that we seek for the double new_pgroup.append(Perm([fmap[f] for f in reorder])) return new_pgroup
def test_flatten(): assert flatten((1, (1, ))) == [1, 1] assert flatten((x, (x, ))) == [x, x] ls = [[(-2, -1), (1, 2)], [(0, 0)]] assert flatten(ls, levels=0) == ls assert flatten(ls, levels=1) == [(-2, -1), (1, 2), (0, 0)] assert flatten(ls, levels=2) == [-2, -1, 1, 2, 0, 0] assert flatten(ls, levels=3) == [-2, -1, 1, 2, 0, 0] pytest.raises(ValueError, lambda: flatten(ls, levels=-1)) class MyOp(Basic): pass assert flatten([MyOp(x, y), z]) == [MyOp(x, y), z] assert flatten([MyOp(x, y), z], cls=MyOp) == [x, y, z] assert flatten({1, 11, 2}) == list({1, 11, 2})
def test_flatten(): assert flatten((1, (1,))) == [1, 1] assert flatten((x, (x,))) == [x, x] ls = [[(-2, -1), (1, 2)], [(0, 0)]] assert flatten(ls, levels=0) == ls assert flatten(ls, levels=1) == [(-2, -1), (1, 2), (0, 0)] assert flatten(ls, levels=2) == [-2, -1, 1, 2, 0, 0] assert flatten(ls, levels=3) == [-2, -1, 1, 2, 0, 0] pytest.raises(ValueError, lambda: flatten(ls, levels=-1)) class MyOp(Basic): pass assert flatten([MyOp(x, y), z]) == [MyOp(x, y), z] assert flatten([MyOp(x, y), z], cls=MyOp) == [x, y, z] assert flatten({1, 11, 2}) == list({1, 11, 2})
def __new__(cls, *args, **kw_args): """The constructor for the Prufer object. Examples ======== >>> from diofant.combinatorics.prufer import Prufer A Prufer object can be constructed from a list of edges: >>> a = Prufer([[0, 1], [0, 2], [0, 3]]) >>> a.prufer_repr [0, 0] If the number of nodes is given, no checking of the nodes will be performed; it will be assumed that nodes 0 through n - 1 are present: >>> Prufer([[0, 1], [0, 2], [0, 3]], 4) Prufer([[0, 1], [0, 2], [0, 3]], 4) A Prufer object can be constructed from a Prufer sequence: >>> b = Prufer([1, 3]) >>> b.tree_repr [[0, 1], [1, 3], [2, 3]] """ ret_obj = Basic.__new__(cls, *args, **kw_args) args = [list(args[0])] if args[0] and iterable(args[0][0]): if not args[0][0]: raise ValueError( 'Prufer expects at least one edge in the tree.') if len(args) > 1: nnodes = args[1] else: nodes = set(flatten(args[0])) nnodes = max(nodes) + 1 if nnodes != len(nodes): missing = set(range(nnodes)) - nodes if len(missing) == 1: msg = 'Node %s is missing.' % missing.pop() else: msg = 'Nodes %s are missing.' % list(sorted(missing)) raise ValueError(msg) ret_obj._tree_repr = [list(i) for i in args[0]] ret_obj._nodes = nnodes else: ret_obj._prufer_repr = args[0] ret_obj._nodes = len(ret_obj._prufer_repr) + 2 return ret_obj
def random_integer_partition(n, seed=None): """ Generates a random integer partition summing to ``n`` as a list of reverse-sorted integers. Examples ======== >>> from diofant.combinatorics.partitions import random_integer_partition For the following, a seed is given so a known value can be shown; in practice, the seed would not be given. >>> random_integer_partition(100, seed=[1, 1, 12, 1, 2, 1, 85, 1]) [85, 12, 2, 1] >>> random_integer_partition(10, seed=[1, 2, 3, 1, 5, 1]) [5, 3, 1, 1] >>> random_integer_partition(1) [1] """ from diofant.utilities.randtest import _randint n = as_int(n) if n < 1: raise ValueError('n must be a positive integer') randint = _randint(seed) partition = [] while (n > 0): k = randint(1, n) mult = randint(1, n//k) partition.append((k, mult)) n -= k*mult partition.sort(reverse=True) partition = flatten([[k]*m for k, m in partition]) return partition
def plot_implicit(expr, x_var=None, y_var=None, **kwargs): """A plot function to plot implicit equations / inequalities. Parameters ========== ``expr`` : Expr The equation / inequality that is to be plotted. ``x_var`` : symbol or tuple, optional symbol to plot on x-axis or tuple giving symbol and range as ``(symbol, xmin, xmax)`` ``y_var`` : symbol or tuple, optional symbol to plot on y-axis or tuple giving symbol and range as ``(symbol, ymin, ymax)`` If neither ``x_var`` nor ``y_var`` are given then the free symbols in the expression will be assigned in the order they are sorted. The following keyword arguments can also be used: ``adaptive`` : Boolean, optional The default value is set to True. It has to be set to False if you want to use a mesh grid. ``depth`` : integer The depth of recursion for adaptive mesh grid. Default value is 0. Takes value in the range (0, 4). ``points`` : integer The number of points if adaptive mesh grid is not used. Default value is 200. ``title`` : str The title for the plot. ``xlabel`` : str The label for the x-axis ``ylabel`` : string The label for the y-axis Aesthetics options: ``line_color`` : float or str Specifies the color for the plot. See ``Plot`` to see how to set color for the plots. plot_implicit, by default, uses interval arithmetic to plot functions. If the expression cannot be plotted using interval arithmetic, it defaults to a generating a contour using a mesh grid of fixed number of points. By setting adaptive to False, you can force plot_implicit to use the mesh grid. The mesh grid method can be effective when adaptive plotting using interval arithmetic, fails to plot with small line width. Examples ======== Plot expressions: >>> from diofant import plot_implicit, cos, sin, symbols, Eq, And >>> x, y = symbols('x y') Without any ranges for the symbols in the expression >>> p1 = plot_implicit(Eq(x**2 + y**2, 5)) With the range for the symbols >>> p2 = plot_implicit(Eq(x**2 + y**2, 3), ... (x, -3, 3), (y, -3, 3)) With depth of recursion as argument. >>> p3 = plot_implicit(Eq(x**2 + y**2, 5), ... (x, -4, 4), (y, -4, 4), depth = 2) Using mesh grid and not using adaptive meshing. >>> p4 = plot_implicit(Eq(x**2 + y**2, 5), ... (x, -5, 5), (y, -2, 2), adaptive=False) Using mesh grid with number of points as input. >>> p5 = plot_implicit(Eq(x**2 + y**2, 5), ... (x, -5, 5), (y, -2, 2), ... adaptive=False, points=400) Plotting regions. >>> p6 = plot_implicit(y > x**2) Plotting Using boolean conjunctions. >>> p7 = plot_implicit(And(y > x, y > -x)) When plotting an expression with a single variable (y - 1, for example), specify the x or the y variable explicitly: >>> p8 = plot_implicit(y - 1, y_var=y) >>> p9 = plot_implicit(x - 1, x_var=x) """ # Represents whether the expression contains an Equality, # GreaterThan or LessThan has_equality = False def arg_expand(bool_expr): """ Recursively expands the arguments of an Boolean Function """ for arg in bool_expr.args: if isinstance(arg, BooleanFunction): arg_expand(arg) elif isinstance(arg, Relational): arg_list.append(arg) arg_list = [] if isinstance(expr, BooleanFunction): arg_expand(expr) # Check whether there is an equality in the expression provided. if any( isinstance(e, (Equality, GreaterThan, LessThan)) for e in arg_list): has_equality = True elif not isinstance(expr, Relational): expr = Eq(expr, 0) has_equality = True elif isinstance(expr, (Equality, GreaterThan, LessThan)): has_equality = True xyvar = [i for i in (x_var, y_var) if i is not None] free_symbols = expr.free_symbols range_symbols = Tuple(*flatten(xyvar)).free_symbols undeclared = free_symbols - range_symbols if len(free_symbols & range_symbols) > 2: raise NotImplementedError("Implicit plotting is not implemented for " "more than 2 variables") # Create default ranges if the range is not provided. default_range = Tuple(-5, 5) def _range_tuple(s): if isinstance(s, (Dummy, Symbol)): return Tuple(s) + default_range if len(s) == 3: return Tuple(*s) raise ValueError('symbol or `(symbol, min, max)` expected but got %s' % s) if len(xyvar) == 0: xyvar = list(_sort_gens(free_symbols)) var_start_end_x = _range_tuple(xyvar[0]) x = var_start_end_x[0] if len(xyvar) != 2: if x in undeclared or not undeclared: xyvar.append(Dummy('f(%s)' % x.name)) else: xyvar.append(undeclared.pop()) var_start_end_y = _range_tuple(xyvar[1]) use_interval = kwargs.pop('adaptive', True) nb_of_points = kwargs.pop('points', 300) depth = kwargs.pop('depth', 0) line_color = kwargs.pop('line_color', "blue") # Check whether the depth is greater than 4 or less than 0. if depth > 4: depth = 4 elif depth < 0: depth = 0 series_argument = ImplicitSeries(expr, var_start_end_x, var_start_end_y, has_equality, use_interval, depth, nb_of_points, line_color) show = kwargs.pop('show', True) # set the x and y limits kwargs['xlim'] = tuple(float(x) for x in var_start_end_x[1:]) kwargs['ylim'] = tuple(float(y) for y in var_start_end_y[1:]) # set the x and y labels kwargs.setdefault('xlabel', var_start_end_x[0].name) kwargs.setdefault('ylabel', var_start_end_y[0].name) p = Plot(series_argument, **kwargs) if show: p.show() return p