Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Trac #17048: Faster Posets.RandomPoset
Browse files Browse the repository at this point in the history
Nathann Cohen wrote on another ticket:

"This code could be seriously rewritten, though. In two different ways:

1) Assume from the start that 0,...,n-1 is a linear extension, and only
add edges i,j with i<j. With this you don't have to call
`is_directed_acyclic` every second (and this is the bottleneck of the
implementation). At the end, relabel everything randomly so that the
linear extension is random, too

2) Work directly on the Hasse Diagram. Build the random Poset on n
elements from a poset on n-1 elements:

Consider all minimal elements `m_1,...m_c` of the previous digraph and
add the edges `m_i,n` with probability `p`. If some edge `m_i` was not
added, consider the immediate predecessors of `m_i` and do the same with
them.

This second way to build them benefits from the transitivity of posets.

The last algorithm was mentionned by Florent and Nicolas to which I
asked the question. They seemed to think that this generation of random
posets was not standard, and that we could change it a bit if we like,
i.e. without caring if by changing the algorithm we change the
distribution of posets. It seems that it is only there to provide random
posets for computer tests, with no specific property in mind."

I add this on wishlist-milestone, so that I don't forget it totally. I'm
not going to code this at least for release 6.4.

URL: http://trac.sagemath.org/17048
Reported by: jmantysalo
Ticket author(s): Jori Mäntysalo
Reviewer(s): Frédéric Chapoton
  • Loading branch information
Release Manager authored and vbraun committed Apr 27, 2016
2 parents 655da7a + 728cba8 commit 46bf5cf
Showing 1 changed file with 21 additions and 21 deletions.
42 changes: 21 additions & 21 deletions src/sage/combinat/posets/poset_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
:meth:`~Posets.IntegerPartitions` | Return the poset of integer partitions of ``n``.
:meth:`~Posets.IntegerPartitionsDominanceOrder` | Return the poset of integer partitions on the integer `n` ordered by dominance.
:meth:`~Posets.PentagonPoset` | Return the Pentagon poset.
:meth:`~Posets.RandomPoset` | Return a random poset on `n` vertices according to a probability `p`.
:meth:`~Posets.RandomPoset` | Return a random poset on `n` elements.
:meth:`~Posets.RestrictedIntegerPartitions` | Return the poset of integer partitions of `n`, ordered by restricted refinement.
:meth:`~Posets.SetPartitions` | Return the poset of set partitions of the set `\{1,\dots,n\}`.
:meth:`~Posets.ShardPoset` | Return the shard intersection order.
Expand Down Expand Up @@ -275,7 +275,7 @@ def DiamondPoset(n, facade = None):
INPUT:
- ``n`` -- number of vertices, an integer at least 3
- ``n`` -- number of elements, an integer at least 3
- ``facade`` (boolean) -- whether to make the returned poset a
facade poset (see :mod:`sage.categories.facade_sets`); the
Expand Down Expand Up @@ -479,31 +479,28 @@ def IntegerPartitionsDominanceOrder(n):
@staticmethod
def RandomPoset(n, p):
r"""
Generate a random poset on ``n`` vertices according to a
Generate a random poset on ``n`` elements according to a
probability ``p``.
INPUT:
- ``n`` - number of vertices, a non-negative integer
- ``n`` - number of elements, a non-negative integer
- ``p`` - a probability, a real number between 0 and 1 (inclusive)
OUTPUT:
A poset on ``n`` vertices. The construction decides to make an
ordered pair of vertices comparable in the poset with probability
``p``, however a pair is not made comparable if it would violate
the defining properties of a poset, such as transitivity.
So in practice, once the probability exceeds a small number the
generated posets may be very similar to a chain. So to create
interesting examples, keep the probability small, perhaps on the
order of `1/n`.
A poset on `n` elements. The probability `p` roughly measures
width/height of the output: `p=0` always generates an antichain,
`p=1` will return a chain. To create interesting examples,
keep the probability small, perhaps on the order of `1/n`.
EXAMPLES::
sage: Posets.RandomPoset(17,.15)
Finite poset containing 17 elements
sage: set_random_seed(0) # Results are reproducible
sage: P = Posets.RandomPoset(5, 0.3)
sage: P.cover_relations()
[[5, 4], [4, 2], [1, 2]]
TESTS::
Expand All @@ -526,8 +523,12 @@ def RandomPoset(n, p):
Traceback (most recent call last):
...
ValueError: probability must be between 0 and 1, not -0.5
sage: Posets.RandomPoset(0, 0.5)
Finite poset containing 0 elements
"""
from sage.misc.prandom import random

try:
n = Integer(n)
except TypeError:
Expand All @@ -541,15 +542,14 @@ def RandomPoset(n, p):
if p < 0 or p> 1:
raise ValueError("probability must be between 0 and 1, not {0}".format(p))

D = DiGraph(loops=False,multiedges=False)
D = DiGraph(loops=False, multiedges=False)
D.add_vertices(range(n))
for i in range(n):
for j in range(n):
for j in range(i+1, n):
if random() < p:
D.add_edge(i,j)
if not D.is_directed_acyclic():
D.delete_edge(i,j)
return Poset(D,cover_relations=False)
D.add_edge(i, j)
D.relabel(list(Permutations(n).random_element()))
return Poset(D, cover_relations=False)

@staticmethod
def SetPartitions(n):
Expand Down

0 comments on commit 46bf5cf

Please sign in to comment.