def permutation(pi, invertible=True): r""" Return the invertible finite discrete dynamical system induced by the permutation ``pi`` of the set `\{1, 2, \ldots, n\}`. The permutation ``pi`` can be provided as an instance of :class:`Permutation`, but also as anything that can be cast into that class. See also :meth:`one_line` for a more general construction, which takes any map from `\{1, 2, \ldots, n\}` to `\{1, 2, \ldots, n\}` given in one-line notation, and builds a (not necessarily invertible) discrete dynamical system out of it. EXAMPLES:: sage: F = finite_dynamical_systems.permutation([3, 5, 4, 1, 2]) sage: F.verify_inverse_evolution() True sage: sorted(F.orbit_lengths()) [2, 3] sage: F.orbit(3) [3, 4, 1] sage: F.is_homomesic(lambda x: 1) True sage: F.is_homomesic(lambda x: x) False """ from sage.combinat.permutation import Permutation pi = Permutation(pi) n = len(pi) X = range(1, n + 1) return InvertibleFiniteDynamicalSystem(X, pi, inverse=pi.inverse(), create_tuple=True)
def PermutationGraph(second_permutation, first_permutation=None): r""" Build a permutation graph from one permutation or from two lists. Definition: If `\sigma` is a permutation of `\{ 1, 2, \ldots, n \}`, then the permutation graph of `\sigma` is the graph on vertex set `\{ 1, 2, \ldots, n \}` in which two vertices `i` and `j` satisfying `i < j` are connected by an edge if and only if `\sigma^{-1}(i) > \sigma^{-1}(j)`. A visual way to construct this graph is as follows: Take two horizontal lines in the euclidean plane, and mark points `1, ..., n` from left to right on the first of them. On the second one, still from left to right, mark `n` points `\sigma(1), \sigma(2), \ldots, \sigma(n)`. Now, link by a segment the two points marked with `1`, then link together the points marked with `2`, and so on. The permutation graph of `\sigma` is the intersection graph of those segments: there exists a vertex in this graph for each element from `1` to `n`, two vertices `i, j` being adjacent if the segments `i` and `j` cross each other. The set of edges of the permutation graph can thus be identified with the set of inversions of the inverse of the given permutation `\sigma`. A more general notion of permutation graph can be defined as follows: If `S` is a set, and `(a_1, a_2, \ldots, a_n)` and `(b_1, b_2, \ldots, b_n)` are two lists of elements of `S`, each of which lists contains every element of `S` exactly once, then the permutation graph defined by these two lists is the graph on the vertex set `S` in which two vertices `i` and `j` are connected by an edge if and only if the order in which these vertices appear in the list `(a_1, a_2, \ldots, a_n)` is the opposite of the order in which they appear in the list `(b_1, b_2, \ldots, b_n)`. When `(a_1, a_2, \ldots, a_n) = (1, 2, \ldots, n)`, this graph is the permutation graph of the permutation `(b_1, b_2, \ldots, b_n) \in S_n`. Notice that `S` does not have to be a set of integers here, but can be a set of strings, tuples, or anything else. We can still use the above visual description to construct the permutation graph, but now we have to mark points `a_1, a_2, \ldots, a_n` from left to right on the first horizontal line and points `b_1, b_2, \ldots, b_n` from left to right on the second horizontal line. INPUT: - ``second_permutation`` -- the unique permutation/list defining the graph, or the second of the two (if the graph is to be built from two permutations/lists). - ``first_permutation`` (optional) -- the first of the two permutations/lists from which the graph should be built, if it is to be built from two permutations/lists. When ``first_permutation is None`` (default), it is set to be equal to ``sorted(second_permutation)``, which yields the expected ordering when the elements of the graph are integers. .. SEEALSO:: - Recognition of Permutation graphs in the :mod:`comparability module <sage.graphs.comparability>`. - Drawings of permutation graphs as intersection graphs of segments is possible through the :meth:`~sage.combinat.permutation.Permutation.show` method of :class:`~sage.combinat.permutation.Permutation` objects. The correct argument to use in this case is ``show(representation = "braid")``. - :meth:`~sage.combinat.permutation.Permutation.inversions` EXAMPLES:: sage: p = Permutations(5).random_element() sage: PG = graphs.PermutationGraph(p) sage: edges = PG.edges(labels=False) sage: set(edges) == set(p.inverse().inversions()) True sage: PG = graphs.PermutationGraph([3,4,5,1,2]) sage: sorted(PG.edges()) [(1, 3, None), (1, 4, None), (1, 5, None), (2, 3, None), (2, 4, None), (2, 5, None)] sage: PG = graphs.PermutationGraph([3,4,5,1,2], [1,4,2,5,3]) sage: sorted(PG.edges()) [(1, 3, None), (1, 4, None), (1, 5, None), (2, 3, None), (2, 5, None), (3, 4, None), (3, 5, None)] sage: PG = graphs.PermutationGraph([1,4,2,5,3], [3,4,5,1,2]) sage: sorted(PG.edges()) [(1, 3, None), (1, 4, None), (1, 5, None), (2, 3, None), (2, 5, None), (3, 4, None), (3, 5, None)] sage: PG = graphs.PermutationGraph(Permutation([1,3,2]), Permutation([1,2,3])) sage: sorted(PG.edges()) [(2, 3, None)] sage: graphs.PermutationGraph([]).edges() [] sage: graphs.PermutationGraph([], []).edges() [] sage: PG = graphs.PermutationGraph("graph", "phrag") sage: sorted(PG.edges()) [('a', 'g', None), ('a', 'h', None), ('a', 'p', None), ('g', 'h', None), ('g', 'p', None), ('g', 'r', None), ('h', 'r', None), ('p', 'r', None)] TESTS:: sage: graphs.PermutationGraph([1, 2, 3], [4, 5, 6]) Traceback (most recent call last): ... ValueError: The two permutations do not contain the same set of elements ... """ if first_permutation is None: first_permutation = sorted(second_permutation) else: if set(second_permutation) != set(first_permutation): raise ValueError("The two permutations do not contain the same " + "set of elements ! It is going to be pretty " + "hard to define a permutation graph from that !") vertex_to_index = {} for i, v in enumerate(first_permutation): vertex_to_index[v] = i + 1 from sage.combinat.permutation import Permutation p2 = Permutation([vertex_to_index[x] for x in second_permutation]) p2 = p2.inverse() g = Graph(name="Permutation graph for " + str(second_permutation)) g.add_vertices(second_permutation) for u, v in p2.inversions(): g.add_edge(first_permutation[u - 1], first_permutation[v - 1]) return g
def PermutationGraph(second_permutation, first_permutation = None): r""" Build a permutation graph from one permutation or from two lists. Definition: If `\sigma` is a permutation of `\{ 1, 2, \ldots, n \}`, then the permutation graph of `\sigma` is the graph on vertex set `\{ 1, 2, \ldots, n \}` in which two vertices `i` and `j` satisfying `i < j` are connected by an edge if and only if `\sigma^{-1}(i) > \sigma^{-1}(j)`. A visual way to construct this graph is as follows: Take two horizontal lines in the euclidean plane, and mark points `1, ..., n` from left to right on the first of them. On the second one, still from left to right, mark `n` points `\sigma(1), \sigma(2), \ldots, \sigma(n)`. Now, link by a segment the two points marked with `1`, then link together the points marked with `2`, and so on. The permutation graph of `\sigma` is the intersection graph of those segments: there exists a vertex in this graph for each element from `1` to `n`, two vertices `i, j` being adjacent if the segments `i` and `j` cross each other. The set of edges of the permutation graph can thus be identified with the set of inversions of the inverse of the given permutation `\sigma`. A more general notion of permutation graph can be defined as follows: If `S` is a set, and `(a_1, a_2, \ldots, a_n)` and `(b_1, b_2, \ldots, b_n)` are two lists of elements of `S`, each of which lists contains every element of `S` exactly once, then the permutation graph defined by these two lists is the graph on the vertex set `S` in which two vertices `i` and `j` are connected by an edge if and only if the order in which these vertices appear in the list `(a_1, a_2, \ldots, a_n)` is the opposite of the order in which they appear in the list `(b_1, b_2, \ldots, b_n)`. When `(a_1, a_2, \ldots, a_n) = (1, 2, \ldots, n)`, this graph is the permutation graph of the permutation `(b_1, b_2, \ldots, b_n) \in S_n`. Notice that `S` does not have to be a set of integers here, but can be a set of strings, tuples, or anything else. We can still use the above visual description to construct the permutation graph, but now we have to mark points `a_1, a_2, \ldots, a_n` from left to right on the first horizontal line and points `b_1, b_2, \ldots, b_n` from left to right on the second horizontal line. INPUT: - ``second_permutation`` -- the unique permutation/list defining the graph, or the second of the two (if the graph is to be built from two permutations/lists). - ``first_permutation`` (optional) -- the first of the two permutations/lists from which the graph should be built, if it is to be built from two permutations/lists. When ``first_permutation is None`` (default), it is set to be equal to ``sorted(second_permutation)``, which yields the expected ordering when the elements of the graph are integers. .. SEEALSO: - Recognition of Permutation graphs in the :mod:`comparability module <sage.graphs.comparability>`. - Drawings of permutation graphs as intersection graphs of segments is possible through the :meth:`~sage.combinat.permutation.Permutation.show` method of :class:`~sage.combinat.permutation.Permutation` objects. The correct argument to use in this case is ``show(representation = "braid")``. - :meth:`~sage.combinat.permutation.Permutation.inversions` EXAMPLES:: sage: p = Permutations(5).random_element() sage: PG = graphs.PermutationGraph(p) sage: edges = PG.edges(labels=False) sage: set(edges) == set(p.inverse().inversions()) True sage: PG = graphs.PermutationGraph([3,4,5,1,2]) sage: sorted(PG.edges()) [(1, 3, None), (1, 4, None), (1, 5, None), (2, 3, None), (2, 4, None), (2, 5, None)] sage: PG = graphs.PermutationGraph([3,4,5,1,2], [1,4,2,5,3]) sage: sorted(PG.edges()) [(1, 3, None), (1, 4, None), (1, 5, None), (2, 3, None), (2, 5, None), (3, 4, None), (3, 5, None)] sage: PG = graphs.PermutationGraph([1,4,2,5,3], [3,4,5,1,2]) sage: sorted(PG.edges()) [(1, 3, None), (1, 4, None), (1, 5, None), (2, 3, None), (2, 5, None), (3, 4, None), (3, 5, None)] sage: PG = graphs.PermutationGraph(Permutation([1,3,2]), Permutation([1,2,3])) sage: sorted(PG.edges()) [(2, 3, None)] sage: graphs.PermutationGraph([]).edges() [] sage: graphs.PermutationGraph([], []).edges() [] sage: PG = graphs.PermutationGraph("graph", "phrag") sage: sorted(PG.edges()) [('a', 'g', None), ('a', 'h', None), ('a', 'p', None), ('g', 'h', None), ('g', 'p', None), ('g', 'r', None), ('h', 'r', None), ('p', 'r', None)] TESTS:: sage: graphs.PermutationGraph([1, 2, 3], [4, 5, 6]) Traceback (most recent call last): ... ValueError: The two permutations do not contain the same set of elements ... """ if first_permutation is None: first_permutation = sorted(second_permutation) else: if set(second_permutation) != set(first_permutation): raise ValueError("The two permutations do not contain the same "+ "set of elements ! It is going to be pretty "+ "hard to define a permutation graph from that !") vertex_to_index = {} for i, v in enumerate(first_permutation): vertex_to_index[v] = i+1 from sage.combinat.permutation import Permutation p2 = Permutation([vertex_to_index[x] for x in second_permutation]) p2 = p2.inverse() g = Graph(name="Permutation graph for "+str(second_permutation)) g.add_vertices(second_permutation) for u,v in p2.inversions(): g.add_edge(first_permutation[u-1], first_permutation[v-1]) return g
def PermutationGraph(second_permutation, first_permutation=None): r""" Builds a permutation graph from one (or two) permutations. General definition A Permutation Graph can be encoded by a permutation `\sigma` of `1, ..., n`. It is then built in the following way : Take two horizontal lines in the euclidean plane, and mark points `1, ..., n` from left to right on the first of them. On the second one, still from left to right, mark point in the order in which they appear in `\sigma`. Now, link by a segment the two points marked with 1, then link together the points marked with 2, and so on. The permutation graph defined by the permutation is the intersection graph of those segments : there exists a point in this graph for each element from `1` to `n`, two vertices `i, j` being adjacent if the segments `i` and `j` cross each other. The set of edges of the resulting graph is equal to the set of inversions of the inverse of the given permutation. INPUT: - ``second_permutation`` -- the permutation from which the graph should be built. It corresponds to the ordering of the elements on the second line (see previous definition) - ``first_permutation`` (optional) -- the ordering of the elements on the *first* line. This is useful when the elements have no natural ordering, for instance when they are strings, or tuples, or anything else. When ``first_permutation == None`` (default), it is set to be equal to ``sorted(second_permutation)``, which just yields the expected ordering when the elements of the graph are integers. .. SEEALSO: - Recognition of Permutation graphs in the :mod:`comparability module <sage.graphs.comparability>`. - Drawings of permutation graphs as intersection graphs of segments is possible through the :meth:`~sage.combinat.permutation.Permutation.show` method of :class:`~sage.combinat.permutation.Permutation` objects. The correct argument to use in this case is ``show(representation = "braid")``. - :meth:`~sage.combinat.permutation.Permutation.inversions` EXAMPLE:: sage: p = Permutations(5).random_element() sage: edges = graphs.PermutationGraph(p).edges(labels =False) sage: set(edges) == set(p.inverse().inversions()) True TESTS:: sage: graphs.PermutationGraph([1, 2, 3], [4, 5, 6]) Traceback (most recent call last): ... ValueError: The two permutations do not contain the same set of elements ... """ if first_permutation == None: first_permutation = sorted(second_permutation) else: if set(second_permutation) != set(first_permutation): raise ValueError("The two permutations do not contain the same " + "set of elements ! It is going to be pretty " + "hard to define a permutation graph from that !") vertex_to_index = {} for i, v in enumerate(first_permutation): vertex_to_index[v] = i + 1 from sage.combinat.permutation import Permutation p2 = Permutation(map(lambda x: vertex_to_index[x], second_permutation)) p1 = Permutation(map(lambda x: vertex_to_index[x], first_permutation)) p2 = p2 * p1.inverse() p2 = p2.inverse() g = Graph(name="Permutation graph for " + str(second_permutation)) g.add_vertices(second_permutation) for u, v in p2.inversions(): g.add_edge(first_permutation[u - 1], first_permutation[v - 1]) return g
def PermutationGraph(second_permutation, first_permutation = None): r""" Builds a permutation graph from one (or two) permutations. General definition A Permutation Graph can be encoded by a permutation `\sigma` of `1, ..., n`. It is then built in the following way : Take two horizontal lines in the euclidean plane, and mark points `1, ..., n` from left to right on the first of them. On the second one, still from left to right, mark point in the order in which they appear in `\sigma`. Now, link by a segment the two points marked with 1, then link together the points marked with 2, and so on. The permutation graph defined by the permutation is the intersection graph of those segments : there exists a point in this graph for each element from `1` to `n`, two vertices `i, j` being adjacent if the segments `i` and `j` cross each other. The set of edges of the resulting graph is equal to the set of inversions of the inverse of the given permutation. INPUT: - ``second_permutation`` -- the permutation from which the graph should be built. It corresponds to the ordering of the elements on the second line (see previous definition) - ``first_permutation`` (optional) -- the ordering of the elements on the *first* line. This is useful when the elements have no natural ordering, for instance when they are strings, or tuples, or anything else. When ``first_permutation == None`` (default), it is set to be equal to ``sorted(second_permutation)``, which just yields the expected ordering when the elements of the graph are integers. .. SEEALSO: - Recognition of Permutation graphs in the :mod:`comparability module <sage.graphs.comparability>`. - Drawings of permutation graphs as intersection graphs of segments is possible through the :meth:`~sage.combinat.permutation.Permutation.show` method of :class:`~sage.combinat.permutation.Permutation` objects. The correct argument to use in this case is ``show(representation = "braid")``. - :meth:`~sage.combinat.permutation.Permutation.inversions` EXAMPLE:: sage: p = Permutations(5).random_element() sage: edges = graphs.PermutationGraph(p).edges(labels =False) sage: set(edges) == set(p.inverse().inversions()) True TESTS:: sage: graphs.PermutationGraph([1, 2, 3], [4, 5, 6]) Traceback (most recent call last): ... ValueError: The two permutations do not contain the same set of elements ... """ if first_permutation == None: first_permutation = sorted(second_permutation) else: if set(second_permutation) != set(first_permutation): raise ValueError("The two permutations do not contain the same "+ "set of elements ! It is going to be pretty "+ "hard to define a permutation graph from that !") vertex_to_index = {} for i, v in enumerate(first_permutation): vertex_to_index[v] = i+1 from sage.combinat.permutation import Permutation p2 = Permutation(map(lambda x:vertex_to_index[x], second_permutation)) p1 = Permutation(map(lambda x:vertex_to_index[x], first_permutation)) p2 = p2 * p1.inverse() p2 = p2.inverse() g = Graph(name="Permutation graph for "+str(second_permutation)) g.add_vertices(second_permutation) for u,v in p2.inversions(): g.add_edge(first_permutation[u-1], first_permutation[v-1]) return g