From 28b0bd5356ae728c46fef4b8b0be18a629740213 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Tue, 27 Jun 2023 12:23:12 +0100 Subject: [PATCH 001/101] Fix linters --- .github/workflows/py-lint.yml | 2 +- tox.ini | 158 ++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 tox.ini diff --git a/.github/workflows/py-lint.yml b/.github/workflows/py-lint.yml index f0728a8..93e6ba5 100644 --- a/.github/workflows/py-lint.yml +++ b/.github/workflows/py-lint.yml @@ -35,7 +35,7 @@ jobs: - name: Install relint run: pip install tox relint - name: Lint using relint - run: tox -e relint -- src/sage/ + run: tox -e relint -- oriented_matroids lint-rst: name: Validate docstring markup as RST runs-on: ubuntu-latest diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..51315d3 --- /dev/null +++ b/tox.ini @@ -0,0 +1,158 @@ +## Configuration for tox. +## Needs tox installed in the system python. +## +## doctest: Run the sage doctests. From the SAGE_ROOT/src directory: +## +## $ tox +## +## Arguments are passed on to "sage -t": +## +## $ tox sage/geometry +## +## To pass on options to "sage -t", use -- to separate it from tox options: +## +## $ tox -- --verbose --optional=sage,pynormaliz --long sage/geometry +## +## pycodestyle: +## +## $ tox -e pycodestyle +## +## Note that on the first run, tox automatically installs pycodestyle +## in a virtual environment. +## +[tox] +envlist = pycodestyle-minimal, relint, rst + +requires = + # For the renamed "allowlist_externals" keyword + tox>=3.18 + + +[testenv:pycodestyle] +description = + check against the Python style conventions of PEP8 +deps = pycodestyle +commands = pycodestyle + +[testenv:pycodestyle-minimal] +## Note that the the pycodestyle linter provided by vscode checks against the +## same minimal conventions as defined below, see the file SAGE_ROOT/.vscode/settings.json. +description = + check against Sage's minimal style conventions + # Check for the following issues: + # E111: indentation is not a multiple of four + # E211: whitespace before '(' + # E271: multiple spaces after keyword + # E306: expected 1 blank line before a nested definition, found 0 + # E401: multiple imports on one line + # E502 the backslash is redundant between brackets + # E701: multiple statements on one line (colon) + # E702: multiple statements on one line (semicolon) + # E703: statement ends with a semicolon + # E711: comparison to None should be ‘if cond is None:’ + # E712: comparison to True should be ‘if cond is True:’ or ‘if cond:’ + # E713 test for membership should be ’not in’ + # E721: do not compare types, use isinstance() + # E722: do not use bare except, specify exception instead + # W291: trailing whitespace + # W293: blank line contains whitespace + # W391: blank line at end of file + # W605: invalid escape sequence ‘x’ + # See https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes +deps = pycodestyle +commands = pycodestyle --select E111,E211,E271,E303,E306,E401,E502,E701,E702,E703,E714,W291,W293,W391,W605,E711,E712,E713,E721,E722 oriented_matroids + pycodestyle --select E111,E306,E401,E703,W293,W391,W605,E712,E713,E714,E721,E722 --filename *.pyx oriented_matroids + +[pycodestyle] +max-line-length = 160 +statistics = True + +[testenv:relint] +description = + check whether some forbidden patterns appear + (includes all patchbot pattern-exclusion plugins) +# https://github.com/codingjoe/relint +# The patterns are in .relint.yml +deps = relint +allowlist_externals = find +commands = find oriented_matroids \ + -name "*\#*" -prune -o \ + -name "*.a" -prune -o \ + -name "*.bak" -prune -o \ + -name "*.bz2" -prune -o \ + -name "*.dia" -prune -o \ + -name "*.gz" -prune -o \ + -name "*.ico" -prune -o \ + -name "*.inv" -prune -o \ + -name "*.JPEG" -prune -o \ + -name "*.jpeg" -prune -o \ + -name "*.JPG" -prune -o \ + -name "*.jpg" -prune -o \ + -name "*.log" -prune -o \ + -name "*.o" -prune -o \ + -name "*.orig" -prune -o \ + -name "*.PDF" -prune -o \ + -name "*.pdf" -prune -o \ + -name "*.PNG" -prune -o \ + -name "*.png" -prune -o \ + -name "*.pyc" -prune -o \ + -name "*.so" -prune -o \ + -name "*.sobj" -prune -o \ + -name "*.sws" -prune -o \ + -name "*.tar" -prune -o \ + -name "*.tgz" -prune -o \ + -name "*.xz" -prune -o \ + -name "*.zip" -prune -o \ + -name "*~*" -prune -o \ + -name ".DS_Store" -prune -o \ + -exec relint -c {toxinidir}/.relint.yml \{\} + + + +[testenv:rst] +description = + validate Python docstrings markup as reStructuredText +deps = flake8-rst-docstrings +commands = flake8 --select=RST oriented_matroids + +[flake8] +rst-roles = + # Sphinx + doc, + file, + ref, + # Sphinx - https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#the-standard-domain (selection) + envvar, + # Sphinx - https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#cross-referencing-python-objects + attr, + class, + const, + data, + exc, + func, + kbd, + meth, + mod, + obj, + # from src/sage/misc/sagedoc.py + arxiv, + doi, + mathscinet, + oeis, + pari, + python, + trac, + issue, + wikipedia +rst-directives = + attribute, + automethod, + autofunction, + toctree, + MODULEAUTHOR, + ONLY, + PLOT, + SEEALSO, + TODO +extend-ignore = + # Ignore RST306 Unknown target name -- because of references to the global bibliography + RST306 From f90618c8d00b242e10d7b3ecf915f254226a9cc5 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Tue, 27 Jun 2023 13:08:01 +0100 Subject: [PATCH 002/101] Update linters and fix some files --- .relint.yml | 63 ++++++++++++++++++++ VERSION | 2 +- oriented_matroids/signed_subset_element.py | 1 - oriented_matroids/signed_vector_element.py | 2 +- oriented_matroids/vector_oriented_matroid.py | 1 - setup.py | 2 +- tox.ini | 14 +++-- 7 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 .relint.yml diff --git a/.relint.yml b/.relint.yml new file mode 100644 index 0000000..7996583 --- /dev/null +++ b/.relint.yml @@ -0,0 +1,63 @@ +# From https://github.com/sagemath/sage-patchbot/blob/master/sage_patchbot/plugins.py +# (simple pattern-exclusion plugins) +# The patterns have been edited slightly because relint tests the regexp to the whole file, +# whereas the patchbots tests them line by line. + +- name: 'python3: Python3 incompatible code' + hint: | + # ifilter, imap, izip # __metaclass__ + # update raise statements # except Exception, var + # six is no longer allowed + pattern: '(import.*[, ]ifilter|import.*[, ]imap|import.*[, ]izip|^\s*raise\s*[A-Za-z]*Error\s*,|__metaclass__|except\s*[A-Za-z]\s*,|import six|from six import)' + filePattern: .*[.](py|pyx|rst) + +- name: 'foreign_latex: foreign commands in LaTeX' + hint: | + use equivalent LaTeX commands instead of plain TeX commands such as \over, \choose, etc. + pattern: '(\\choose|\\atop|\\above|\\overwithdelims|\\atopwithdelims|\\abovewithdelims)' + # \over appears in bad latex code coming from Fricas and Maxima + +- name: 'blocks: wrong syntax for blocks (INPUT, OUTPUT, EXAMPLES, NOTE, etc.)' + hint: | + # the correct syntax is .. SEEALSO:: + # TESTS and EXAMPLES should be plural, NOTE singular + # no :: after INPUT, OUTPUT, REFERENCE blocks + # no " :" at the end of lines + pattern: '(\.\.SEE|SEE ALSO|SEEALSO:($|[^:])|^\s*TEST:|^\s*EXAMPLE:|^\s*NOTES:|^\s*[A-Z]*PUT::|^\s*REFERENCES?::$)' + +- name: 'trac_links: bad trac link' + hint: | + the correct syntax for trac roles is :trac:`NUMBER`, note the initial colon + pattern: '[^:]trac:`[0-9]' + +- name: 'triple_colon: triple colon (::: or : ::)' + pattern: ':[ ]*::$' + +# From various typo tickets + +# https://github.com/sagemath/sage/issues/30585 +- name: 'typo "homogenous" detected' + hint: | + in mathematics it should be "homogeneous" + pattern: 'homogenous' + +# Modularization anti-patterns + +- name: 'namespace_pkg_all_import: import from .all of a namespace package' + hint: | + Sage library code should not import from sage.PAC.KAGE.all when sage.PAC.KAGE is an implicit + namespace package. Type import_statements("SOME_IDENTIFIER") to find a more specific import, + or use 'sage --fiximports' to fix automatically in the source file. + # Keep in sync with SAGE_ROOT/src/sage/misc/replace_dot_all.py + pattern: 'from\s+sage(|[.](arith|categories|combinat|crypto|databases|data_structures|dynamics|ext|game_theory|games|graphs|groups|interfaces|manifolds|matrix|matroids|misc|modules|monoids|numerical|probability|quadratic_forms|quivers|rings|sat|schemes|sets|stats|symbolic|tensor)[a-z0-9_.]*|[.]libs)[.]all\s+import' + # imports from .all are allowed in all.py; also allow in some modules that need sage.all + filePattern: '(.*/|)(?!(all|benchmark|dev_tools|parsing|sage_eval))[^/.]*[.](py|pyx|pxi)$' + +# Magic doctest comments + +- name: 'multiline_doctest_comment: magic comment on a continuation line' + hint: | + magic doctest comments should appear on the "sage:" line, not "....:" lines + # see optional_regex in src/sage/doctest/parsing.py + # "indirect doctest" is from src/bin/sage-coverage + pattern: '^[ ]*[.][.][.][.]:.*#.*(arb216|arb218|py2|py3|long time|not implemented|not tested|known bug|optional|indirect doctest)' diff --git a/VERSION b/VERSION index 4e379d2..6e8bf73 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.0.2 +0.1.0 diff --git a/oriented_matroids/signed_subset_element.py b/oriented_matroids/signed_subset_element.py index ae94a41..64cb614 100644 --- a/oriented_matroids/signed_subset_element.py +++ b/oriented_matroids/signed_subset_element.py @@ -568,4 +568,3 @@ def is_zero(self): Return whether or not element is 0 """ return len([1 for e in self.groundset() if self(e) != 0]) == 0 - diff --git a/oriented_matroids/signed_vector_element.py b/oriented_matroids/signed_vector_element.py index 2350e50..bddb27e 100644 --- a/oriented_matroids/signed_vector_element.py +++ b/oriented_matroids/signed_vector_element.py @@ -74,7 +74,7 @@ class SignedVectorElement(SignedSubsetElement): - :class:`oriented_matroids.signed_subset_element.SignedSubsetElement` """ - def __init__(self, parent=None, data=None, groundset=None, \ + def __init__(self, parent=None, data=None, groundset=None, positives=None, negatives=None, zeroes=None): """ Initialize ``self``. diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index a453e43..93ed952 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -236,4 +236,3 @@ def circuits(self): vecs = [v for v in self.vectors() if not v.is_zero()] P = Poset([vecs, lambda x,y: x.is_restriction_of(y)]) return P.minimal_elements() - diff --git a/setup.py b/setup.py index 3bc41b0..3cfa0bf 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ def run_tests(self): long_description_content_type="text/markdown", url='https://github.com/thecaligarmo/oriented_matroids', author='Aram Dermenjian', - author_email='aram.dermenjian@gmail.com', # choose a main contact email + author_email='aram.dermenjian.math@gmail.com', # choose a main contact email license='GPLv3+', # This should be consistent with the LICENCE file classifiers=[ # How mature is this project? Common values are diff --git a/tox.ini b/tox.ini index 51315d3..f200224 100644 --- a/tox.ini +++ b/tox.ini @@ -22,11 +22,17 @@ ## [tox] envlist = pycodestyle-minimal, relint, rst +skipsdist = true requires = # For the renamed "allowlist_externals" keyword tox>=3.18 +[testenv] +passenv = + local: SKIP_BOOTSTRAP + local: SKIP_SYSTEM_PKG_INSTALL + local: SKIP_CONFIGURE [testenv:pycodestyle] description = @@ -60,8 +66,8 @@ description = # W605: invalid escape sequence ‘x’ # See https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes deps = pycodestyle -commands = pycodestyle --select E111,E211,E271,E303,E306,E401,E502,E701,E702,E703,E714,W291,W293,W391,W605,E711,E712,E713,E721,E722 oriented_matroids - pycodestyle --select E111,E306,E401,E703,W293,W391,W605,E712,E713,E714,E721,E722 --filename *.pyx oriented_matroids +commands = pycodestyle --select E111,E211,E271,E303,E306,E401,E502,E701,E702,E703,E714,W291,W293,W391,W605,E711,E712,E713,E721,E722 {posargs:{toxinidir}/oriented_matroids/} + pycodestyle --select E111,E306,E401,E703,W293,W391,W605,E712,E713,E714,E721,E722 --filename *.pyx oriented_matroids {posargs:{toxinidir}/oriented_matroids/} [pycodestyle] max-line-length = 160 @@ -75,7 +81,7 @@ description = # The patterns are in .relint.yml deps = relint allowlist_externals = find -commands = find oriented_matroids \ +commands = find {posargs:{toxinidir}/oriented_matroids/} \ -name "*\#*" -prune -o \ -name "*.a" -prune -o \ -name "*.bak" -prune -o \ @@ -112,7 +118,7 @@ commands = find oriented_matroids \ description = validate Python docstrings markup as reStructuredText deps = flake8-rst-docstrings -commands = flake8 --select=RST oriented_matroids +commands = flake8 --select=RST {posargs:{toxinidir}/oriented_matroids/} [flake8] rst-roles = From 866bc0d97df0029d5ca4ceafd6ee763326700a8a Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Tue, 27 Jun 2023 13:16:27 +0100 Subject: [PATCH 003/101] Fix RST bugs --- .../.signed_vector_element.py.swp | Bin 0 -> 16384 bytes .../oriented_matroids_category.py | 2 +- oriented_matroids/signed_subset_element.py | 23 +++++++++--------- oriented_matroids/signed_vector_element.py | 21 ++++++++-------- 4 files changed, 22 insertions(+), 24 deletions(-) create mode 100644 oriented_matroids/.signed_vector_element.py.swp diff --git a/oriented_matroids/.signed_vector_element.py.swp b/oriented_matroids/.signed_vector_element.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..e47ced945c6e23991aa11240a4f020849b7d2d6e GIT binary patch literal 16384 zcmeHN%WoS+7$0a;-UW)_0GA;>#5VTE2}o@Xt%%a7Ei_HkJU|Mmy|%~pmi4aLT_;Ti z;!p{=ApsH(2`Cabgv0^Cg$gR6g5bhK0tx;CKth}VQGxhn{_eT zT$4YpX9*_|)nd~OJlCrFqrEY{RdGy|Fe&A=7NfLUd1FZBAF z7W_E>kJkU^Z)WT)@Con=@G|faumiXixE8nu_C0hz_Y+U;1=NA4X7J<82I~o#=Znj0mp!4;11x+>lk|j zm<4tKpI*z@Gr%6;mundN8Tb+S0eAyA2pj;;Z)5BoUR5d=7HOR@32Ag1@JEL7H}Fk35)@G;7(vW@HIACz5>nw9|2DS!@%7D z^#S4SX!C_J-u=+si2|SGd-)Py8q4BuIjaKQIq`ns%=zW4ES*Df1oGK1kQ-AWijbl8 zDky<9&u#La+ZsmS+ZxC}}>KrdnPU#}kj98=L;b9rBiW)DH zfMUuQb}ii@pOmM#EN__}q-S~649qOAdv4pQ`T`Lx*S7*|Mfh3nh&rl}!IQ#sg`bY= zQq0V?%P12vV-$;)V+F-xDrrxo64iSMiI!Al8VWuM{0C7G%P`_4TEu$)w|M}^p%20SdJGew(0wY(gn@NmjuL@eEP6b8c1AE z1;vUPh`Q^o8C~|{Z%$yhn38IyVeq-BsfojLGo4nLqEVF1C%vugyw7MzO=pQx4D6^( zccE#dbu}S1ndOg*wY?)1S6z}C$tIn#G$KZ_BQ>BtvYZHmcv32f7)&KuCMlGX9^xXU zgk=&bs_KCnmJ~AZ6!?;KP|`;&<&__#DCrO>fH=4|l_?34-^(K{zq}k@IIYy@T201wgo2%ZxTC-Qi+>R6)~~vLQLTDvVhwQ zl)K3xS$Phm<#Id)r(w43pn!PtGo@0Rn|2^PM>;<$UMi85!(Z{ahTFEQB+rbx!sLT1 z*GH93O*gI0pt^Kc)<>649xqv!wol)ypdsQu<2CxqaLbXgL}~m1plq=d;L;K)D*8&f z9=B@TLGN(O=M_)DJH~>-Op*iY+*rtcCOw3m% zD-A273?~!o&F|rvjOpWxU9~DfCPM~AiqjiD+@`n2ePuEYb48Hb^LZwwIg^b#j&oTo zu20rRf`W$SRb`s0x~Jx#;R$4;@!==+*DTKuLc;`OlFQ`7POrW|ldEz4aXXYtjwGQh z{yR*(Ww(8r8#FCP1!%l=sitT}H&cIM%u;nV*S6hNvWS}N;r6VrKG@V>YHVF-D0Wo8 zY6T5gj}icO4L)f)7>iLO>cSD8w2bmv{O#`g_=Ix~s#n>KG7?FUoDy-jd>j+LNbl(W zE?@B5rfsh&I^?`SS<0a!vkUX#6l+o%Cip_r!)YH6Zwg0)K=q$T6AdY(-yAd5XC6Vb zIJU8eUOyR$JZv9XZ0BWt*iKk)*V71sR$+8>b#>LKJ8i@D>Z7(*5e{r;lUf6g5b0gBo&=>TWg+GZv;Fwndam9u|0gkGn;%rird_GxhZ615V;;DQlwfgzbiL3o-RZ)XucvmALfrW;KKaDnWJ+s4Y&#TMW`(> zMnI1I;K8>^*W}A(42sc>bXX>woeCRlp321wij6H7>~yR`XvD+?ZQYz2P8TK+wt1 A7ytkO literal 0 HcmV?d00001 diff --git a/oriented_matroids/oriented_matroids_category.py b/oriented_matroids/oriented_matroids_category.py index 69fbd2b..2ceb748 100644 --- a/oriented_matroids/oriented_matroids_category.py +++ b/oriented_matroids/oriented_matroids_category.py @@ -36,7 +36,7 @@ class OrientedMatroids(Category): and `Z^- \subseteq \left(X^- \cup Y^-\right) \backslash \left\{e\right\}`. - See :Wikipedia:`Oriented_matroid` for details. + See :wikipedia:`Oriented_matroid` for details. EXAMPLES:: diff --git a/oriented_matroids/signed_subset_element.py b/oriented_matroids/signed_subset_element.py index 64cb614..d220fd8 100644 --- a/oriented_matroids/signed_subset_element.py +++ b/oriented_matroids/signed_subset_element.py @@ -31,27 +31,26 @@ class SignedSubsetElement(Element): INPUT: - ``parent`` -- the parent object of the element. Usually is a class - generated by :class:`OrientedMatroid`. + generated by :class:`OrientedMatroid`. - ``data`` -- (default: ``None``) is a tuple with information. Can be - given in one of the following formats: + given in one of the following formats: + **as a vector** -- this is a tuple of pluses, minuses, and zeroes. + **as three tuples** -- the first tuple is the positives, the second the negatives and the third the zeroes. + **as a dict** -- the dictionary should have keys *positives*, *negatives*, and *zeroes*. + - ``groundset`` -- (default: ``None``) if not given will construct - the groundset from the parent, or if none is created in the parent, - using the elements found in the data. + the groundset from the parent, or if none is created in the parent, + using the elements found in the data. - ``positives`` -- (default: ``None``) alternative to ``data``. Should be - a tuple of elements. Requires ``negatives`` to be set. + a tuple of elements. Requires ``negatives`` to be set. - ``negatives`` -- (default: ``None``) alternative to ``data``. Should be - a tuple of elements. Requires ``positives`` to be set. + a tuple of elements. Requires ``positives`` to be set. - ``zeroes`` -- (default: ``None``) alternative to ``data``. Should be a - tuple of elements. Requires ``positives`` and ``negatives`` to be set. - - EXAMPLES: + tuple of elements. Requires ``positives`` and ``negatives`` to be set. - Some examples of element constructions:: + EXAMPLES:: sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: from oriented_matroids.signed_subset_element import SignedSubsetElement @@ -70,8 +69,8 @@ class SignedSubsetElement(Element): -: 0: - Elements are also lazy loaded to return the sign of elements from the grou -ndset:: + Elements are also lazy loaded to return the sign of elements from the + groundset:: sage: M = OrientedMatroid([[1],[-1]],key='circuit', groundset=['e']) sage: C = M.elements(); C[0] diff --git a/oriented_matroids/signed_vector_element.py b/oriented_matroids/signed_vector_element.py index bddb27e..6087185 100644 --- a/oriented_matroids/signed_vector_element.py +++ b/oriented_matroids/signed_vector_element.py @@ -30,27 +30,26 @@ class SignedVectorElement(SignedSubsetElement): INPUT: - ``parent`` -- the parent object of the element. Usually is a class - generated by :class:`OrientedMatroid`. + generated by :class:`OrientedMatroid`. - ``data`` -- (default: ``None``) is a tuple with information. Can be - given in one of the following formats: + given in one of the following formats: + **as a vector** -- this is a tuple of pluses, minuses, and zeroes. + **as three tuples** -- the first tuple is the positives, the second the negatives and the third the zeroes. + **as a dict** -- the dictionary should have keys *positives*, *negatives*, and *zeroes*. + - ``groundset`` -- (default: ``None``) if not given will construct - the groundset from the parent, or if none is created in the parent, - using the elements found in the data. + the groundset from the parent, or if none is created in the parent, + using the elements found in the data. - ``positives`` -- (default: ``None``) alternative to ``data``. Should be - a tuple of elements. Requires ``negatives`` to be set. + a tuple of elements. Requires ``negatives`` to be set. - ``negatives`` -- (default: ``None``) alternative to ``data``. Should be - a tuple of elements. Requires ``positives`` to be set. + a tuple of elements. Requires ``positives`` to be set. - ``zeroes`` -- (default: ``None``) alternative to ``data``. Should be a - tuple of elements. Requires ``positives`` and ``negatives`` to be set. - - EXAMPLES: + tuple of elements. Requires ``positives`` and ``negatives`` to be set. - Some examples of element constructions:: + EXAMPLES:: sage: from oriented_matroids import OrientedMatroid sage: from oriented_matroids.signed_vector_element import SignedVectorElement @@ -66,12 +65,12 @@ class SignedVectorElement(SignedSubsetElement): sage: SignedVectorElement(M,data = (1,-1,0)) (1,-1,0) - .. SEEALSO:: - :class:`oriented_matroids.oriented_matroid.OrientedMatroid` - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` - :class:`oriented_matroids.signed_subset_element.SignedSubsetElement` + """ def __init__(self, parent=None, data=None, groundset=None, From 6d83af083f75c243efb183de84276b0013ec3935 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Thu, 29 Jun 2023 11:16:52 +0100 Subject: [PATCH 004/101] Add files for packages --- SPKG.rst | 19 +++++++++++++++++++ dependencies | 4 ++++ makefile | 2 +- spkg-build.in | 3 +++ spkg-install.in | 2 ++ type | 1 + 6 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 SPKG.rst create mode 100644 dependencies create mode 100644 spkg-build.in create mode 100644 spkg-install.in create mode 100644 type diff --git a/SPKG.rst b/SPKG.rst new file mode 100644 index 0000000..053a266 --- /dev/null +++ b/SPKG.rst @@ -0,0 +1,19 @@ +PACKAGE_NAME: oriented_matroids + +Description +----------- + +This package contains an oriented matroid implementation for sagemath. + +License +------- + +GPLv3+ + +Upstream Contact +---------------- + +https://github.com/thecaligarmo/oriented_matroids + + + diff --git a/dependencies b/dependencies new file mode 100644 index 0000000..4f00de2 --- /dev/null +++ b/dependencies @@ -0,0 +1,4 @@ +# no dependencies + +---------- +All lines of this file are ignored except the first. diff --git a/makefile b/makefile index 068382e..fced82d 100644 --- a/makefile +++ b/makefile @@ -4,7 +4,7 @@ PACKAGE = oriented_matroids # change to your sage command if needed -SAGE = /sage/sage/sage +SAGE = /sage/sagedev/sage all: install test diff --git a/spkg-build.in b/spkg-build.in new file mode 100644 index 0000000..ffb822c --- /dev/null +++ b/spkg-build.in @@ -0,0 +1,3 @@ +cd src +sdh_configure +sdh_make diff --git a/spkg-install.in b/spkg-install.in new file mode 100644 index 0000000..3ea8c05 --- /dev/null +++ b/spkg-install.in @@ -0,0 +1,2 @@ +cd src +sdh_make_install diff --git a/type b/type new file mode 100644 index 0000000..9839eb2 --- /dev/null +++ b/type @@ -0,0 +1 @@ +experimental From 0d772b58e1832e27da9eb2ae6e923ba10e27fa14 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Thu, 29 Jun 2023 11:54:16 +0100 Subject: [PATCH 005/101] Update package files --- CHANGELOG.md | 9 +++++++++ Dockerfile | 2 +- SPKG.rst | 19 ------------------- dependencies | 4 ---- pyproject.toml | 3 +++ setup.py | 22 +++++++--------------- spkg-build.in | 3 --- spkg-install.in | 2 -- type | 1 - 9 files changed, 20 insertions(+), 45 deletions(-) delete mode 100644 SPKG.rst delete mode 100644 dependencies create mode 100644 pyproject.toml delete mode 100644 spkg-build.in delete mode 100644 spkg-install.in delete mode 100644 type diff --git a/CHANGELOG.md b/CHANGELOG.md index b444a5b..3ca3d68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes will be made in this file. +## [0.1.0] - + +### Added + +### Changed + +### Fixed + + ## [0.0.2] - 2020-12-15 ### Added diff --git a/Dockerfile b/Dockerfile index ad5d9b6..903eac5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # Dockerfile for binder # Reference: https://mybinder.readthedocs.io/en/latest/dockerfile.html#preparing-your-dockerfile -FROM sagemath/sagemath:9.2 +FROM sagemath/sagemath:10.0 # Copy the contents of the repo in ${HOME} COPY --chown=sage:sage . ${HOME} diff --git a/SPKG.rst b/SPKG.rst deleted file mode 100644 index 053a266..0000000 --- a/SPKG.rst +++ /dev/null @@ -1,19 +0,0 @@ -PACKAGE_NAME: oriented_matroids - -Description ------------ - -This package contains an oriented matroid implementation for sagemath. - -License -------- - -GPLv3+ - -Upstream Contact ----------------- - -https://github.com/thecaligarmo/oriented_matroids - - - diff --git a/dependencies b/dependencies deleted file mode 100644 index 4f00de2..0000000 --- a/dependencies +++ /dev/null @@ -1,4 +0,0 @@ -# no dependencies - ----------- -All lines of this file are ignored except the first. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..638dd9c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index 3cfa0bf..80e0461 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,3 @@ -# -*- encoding: utf-8 -*- import os import sys from setuptools import setup @@ -12,8 +11,6 @@ def readfile(filename): return f.read() # For the tests - - class SageTest(TestCommand): def run_tests(self): errno = os.system("sage -t --force-lib oriented_matroids") @@ -23,26 +20,21 @@ def run_tests(self): setup( name="oriented_matroids", - # the VERSION file is shared with the documentation - version=readfile("VERSION").strip(), description='Oriented matroids for sagemath', - # long_description = readfile("README.rst"), - # get the long description from the README - # For a Markdown README replace the above line by the following two lines: - long_description=readfile("README.md"), - long_description_content_type="text/markdown", + version=readfile('VERSION').strip(), + long_description=readfile('README.md'), + long_description_content_type='text/markdown', url='https://github.com/thecaligarmo/oriented_matroids', author='Aram Dermenjian', author_email='aram.dermenjian.math@gmail.com', # choose a main contact email + project_urls={ + 'Bug Tracker': 'https://github.com/thecaligarmo/oriented_matroids/issues', + }, license='GPLv3+', # This should be consistent with the LICENCE file + python_requires='>=3.8', classifiers=[ - # How mature is this project? Common values are - # 3 - Alpha - # 4 - Beta - # 5 - Production/Stable 'Development Status :: 3 - Alpha', 'Intended Audience :: Science/Research', - 'Topic :: Software Development :: Build Tools', 'Topic :: Scientific/Engineering :: Mathematics', 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', 'Programming Language :: Python :: 3.8.5', diff --git a/spkg-build.in b/spkg-build.in deleted file mode 100644 index ffb822c..0000000 --- a/spkg-build.in +++ /dev/null @@ -1,3 +0,0 @@ -cd src -sdh_configure -sdh_make diff --git a/spkg-install.in b/spkg-install.in deleted file mode 100644 index 3ea8c05..0000000 --- a/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_make_install diff --git a/type b/type deleted file mode 100644 index 9839eb2..0000000 --- a/type +++ /dev/null @@ -1 +0,0 @@ -experimental From d2530619530cb50791bbaa728854d655b9a373d8 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Thu, 29 Jun 2023 12:17:38 +0100 Subject: [PATCH 006/101] Replicate labbe --- MANIFEST.in | 1 + pyproject.toml | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) create mode 100644 MANIFEST.in delete mode 100644 pyproject.toml diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..bb3ec5f --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include README.md diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 638dd9c..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,3 +0,0 @@ -[build-system] -requires = ["setuptools>=61.0"] -build-backend = "setuptools.build_meta" From 23b73eebe0af3be9fac2fa0ae7fbaa457f063b56 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Thu, 29 Jun 2023 13:03:53 +0100 Subject: [PATCH 007/101] Update project info --- MANIFEST.in | 1 + pyproject.toml | 3 +++ setup.py | 5 ++--- 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 pyproject.toml diff --git a/MANIFEST.in b/MANIFEST.in index bb3ec5f..a17c59a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1,2 @@ include README.md +include VERSION diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..638dd9c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index 80e0461..ad210bd 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ import os import sys -from setuptools import setup +from setuptools import setup, find_packages from codecs import open # To open the README file with proper encoding from setuptools.command.test import test as TestCommand # for tests @@ -37,10 +37,9 @@ def run_tests(self): 'Intended Audience :: Science/Research', 'Topic :: Scientific/Engineering :: Mathematics', 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', - 'Programming Language :: Python :: 3.8.5', ], # classifiers list: https://pypi.python.org/pypi?%3Aaction=list_classifiers keywords="SageMath packaging", - packages=['oriented_matroids'], + packages=find_packages(), cmdclass={'test': SageTest}, # adding a special setup command for tests setup_requires=['sage-package'], install_requires=['sage-package', 'sphinx'], From fa3259611e48bc087d71178fdebc128c46789989 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Thu, 29 Jun 2023 13:18:45 +0100 Subject: [PATCH 008/101] Update versions and attempt to fix package --- VERSION | 2 +- oriented_matroids/__init__.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index 6e8bf73..8588ead 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0 +0.1.1.a diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py index 6202b25..1bdd1cd 100644 --- a/oriented_matroids/__init__.py +++ b/oriented_matroids/__init__.py @@ -2,6 +2,6 @@ from .oriented_matroid import OrientedMatroid from .oriented_matroids_category import OrientedMatroids -from sage.misc.lazy_import import lazy_import -lazy_import('sage.matroids.oriented_matroids', - 'oriented_matroids_catalog', 'oriented_matroids') +# from sage.misc.lazy_import import lazy_import +#lazy_import('sage.matroids.oriented_matroids', +# 'oriented_matroids_catalog', 'oriented_matroids') From 5bce686ac1fe32c2dcfcd765ceb5e9fece06efc4 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Fri, 30 Jun 2023 11:26:28 +0100 Subject: [PATCH 009/101] Update version and information --- README.md | 40 +++++++++++++++--- VERSION | 2 +- .../.signed_vector_element.py.swp | Bin 16384 -> 0 bytes oriented_matroids/all.py | 12 +++--- 4 files changed, 41 insertions(+), 13 deletions(-) delete mode 100644 oriented_matroids/.signed_vector_element.py.swp diff --git a/README.md b/README.md index 0d0c8bf..117f8ef 100644 --- a/README.md +++ b/README.md @@ -6,25 +6,53 @@ This package contains an oriented matroid implementation for sagemath. **NOTE:** This package currently does not work. If you would like to help with the development, please let Aram know. -The current version is 0.0.2 and is compatible with sagemath 9.2. +The current version is 0.1.0 and is compatible with sagemath 10.0. ## Installation +### Installation from Pypi +Use `pip` to install the package: + +``` +$ sage -pip install --index-url https://test.pypi.org/simple/ --no-deps oriented_matroids +``` + ### Local install from source Download the source from the git repository: - -`$ git clone https://github.com/thecaligarmo/oriented_matroids.git` +``` +$ git clone https://github.com/thecaligarmo/oriented_matroids.git +``` Change to the root directory and run: - -`$ sage -pip install .` +``` +$ sage -pip install . +``` For convenience this package contains a makefile with this and other often used commands. Should you wish too, you can use the shorthand: -`$ make install` +``` +$ make install +``` Note that you might need to alter the make file in order for this to run properly if your sage is located in another directory. ### Common errors If you get "SSL" errors, try the fixes found on: [ask sagemath](https://ask.sagemath.org/question/51130/ssl-error-using-sage-pip-install-to-download-a-package/) + +## Using the package after install +After install, you can start sage and run the following command to have all methods available: +``` +from oriented_matroids import * +``` + +## Uninstall +To uninstall the package you can run the following command +``` +$ sage -pip uninstall oriented_matroids +``` + +Alternatively, if you installed locally and want to uninstall using `make`, you can run: +``` +$ make uninstall +``` diff --git a/VERSION b/VERSION index 8588ead..6e8bf73 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.1.a +0.1.0 diff --git a/oriented_matroids/.signed_vector_element.py.swp b/oriented_matroids/.signed_vector_element.py.swp deleted file mode 100644 index e47ced945c6e23991aa11240a4f020849b7d2d6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeHN%WoS+7$0a;-UW)_0GA;>#5VTE2}o@Xt%%a7Ei_HkJU|Mmy|%~pmi4aLT_;Ti z;!p{=ApsH(2`Cabgv0^Cg$gR6g5bhK0tx;CKth}VQGxhn{_eT zT$4YpX9*_|)nd~OJlCrFqrEY{RdGy|Fe&A=7NfLUd1FZBAF z7W_E>kJkU^Z)WT)@Con=@G|faumiXixE8nu_C0hz_Y+U;1=NA4X7J<82I~o#=Znj0mp!4;11x+>lk|j zm<4tKpI*z@Gr%6;mundN8Tb+S0eAyA2pj;;Z)5BoUR5d=7HOR@32Ag1@JEL7H}Fk35)@G;7(vW@HIACz5>nw9|2DS!@%7D z^#S4SX!C_J-u=+si2|SGd-)Py8q4BuIjaKQIq`ns%=zW4ES*Df1oGK1kQ-AWijbl8 zDky<9&u#La+ZsmS+ZxC}}>KrdnPU#}kj98=L;b9rBiW)DH zfMUuQb}ii@pOmM#EN__}q-S~649qOAdv4pQ`T`Lx*S7*|Mfh3nh&rl}!IQ#sg`bY= zQq0V?%P12vV-$;)V+F-xDrrxo64iSMiI!Al8VWuM{0C7G%P`_4TEu$)w|M}^p%20SdJGew(0wY(gn@NmjuL@eEP6b8c1AE z1;vUPh`Q^o8C~|{Z%$yhn38IyVeq-BsfojLGo4nLqEVF1C%vugyw7MzO=pQx4D6^( zccE#dbu}S1ndOg*wY?)1S6z}C$tIn#G$KZ_BQ>BtvYZHmcv32f7)&KuCMlGX9^xXU zgk=&bs_KCnmJ~AZ6!?;KP|`;&<&__#DCrO>fH=4|l_?34-^(K{zq}k@IIYy@T201wgo2%ZxTC-Qi+>R6)~~vLQLTDvVhwQ zl)K3xS$Phm<#Id)r(w43pn!PtGo@0Rn|2^PM>;<$UMi85!(Z{ahTFEQB+rbx!sLT1 z*GH93O*gI0pt^Kc)<>649xqv!wol)ypdsQu<2CxqaLbXgL}~m1plq=d;L;K)D*8&f z9=B@TLGN(O=M_)DJH~>-Op*iY+*rtcCOw3m% zD-A273?~!o&F|rvjOpWxU9~DfCPM~AiqjiD+@`n2ePuEYb48Hb^LZwwIg^b#j&oTo zu20rRf`W$SRb`s0x~Jx#;R$4;@!==+*DTKuLc;`OlFQ`7POrW|ldEz4aXXYtjwGQh z{yR*(Ww(8r8#FCP1!%l=sitT}H&cIM%u;nV*S6hNvWS}N;r6VrKG@V>YHVF-D0Wo8 zY6T5gj}icO4L)f)7>iLO>cSD8w2bmv{O#`g_=Ix~s#n>KG7?FUoDy-jd>j+LNbl(W zE?@B5rfsh&I^?`SS<0a!vkUX#6l+o%Cip_r!)YH6Zwg0)K=q$T6AdY(-yAd5XC6Vb zIJU8eUOyR$JZv9XZ0BWt*iKk)*V71sR$+8>b#>LKJ8i@D>Z7(*5e{r;lUf6g5b0gBo&=>TWg+GZv;Fwndam9u|0gkGn;%rird_GxhZ615V;;DQlwfgzbiL3o-RZ)XucvmALfrW;KKaDnWJ+s4Y&#TMW`(> zMnI1I;K8>^*W}A(42sc>bXX>woeCRlp321wij6H7>~yR`XvD+?ZQYz2P8TK+wt1 A7ytkO diff --git a/oriented_matroids/all.py b/oriented_matroids/all.py index 4a3ec8d..c14aa58 100644 --- a/oriented_matroids/all.py +++ b/oriented_matroids/all.py @@ -1,8 +1,8 @@ from __future__ import absolute_import -from .oriented_matroid import OrientedMatroid -from .oriented_matroids_category import OrientedMatroids +from oriented_matroid import OrientedMatroid +from oriented_matroids_category import OrientedMatroids -from sage.misc.lazy_import import lazy_import -lazy_import('sage.matroids.oriented_matroids', - 'oriented_matroids_catalog', - 'oriented_matroids') +# from sage.misc.lazy_import import lazy_import +# lazy_import('sage.matroids.oriented_matroids', +# 'oriented_matroids_catalog', +# 'oriented_matroids') From 7c600b462a6a049eea9b88de4c61d7f0ad8e8550 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Mon, 3 Jul 2023 16:02:22 +0100 Subject: [PATCH 010/101] Removing lines for init --- oriented_matroids/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py index 1bdd1cd..7ad0a4b 100644 --- a/oriented_matroids/__init__.py +++ b/oriented_matroids/__init__.py @@ -2,6 +2,6 @@ from .oriented_matroid import OrientedMatroid from .oriented_matroids_category import OrientedMatroids -# from sage.misc.lazy_import import lazy_import +from sage.misc.lazy_import import lazy_import #lazy_import('sage.matroids.oriented_matroids', # 'oriented_matroids_catalog', 'oriented_matroids') From 731c4cf1f8b10c870af67b0ac966fadff337e38a Mon Sep 17 00:00:00 2001 From: lizzy Date: Mon, 3 Jul 2023 17:02:30 +0100 Subject: [PATCH 011/101] Removing # keys --- oriented_matroids/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py index 7ad0a4b..6202b25 100644 --- a/oriented_matroids/__init__.py +++ b/oriented_matroids/__init__.py @@ -3,5 +3,5 @@ from .oriented_matroids_category import OrientedMatroids from sage.misc.lazy_import import lazy_import -#lazy_import('sage.matroids.oriented_matroids', -# 'oriented_matroids_catalog', 'oriented_matroids') +lazy_import('sage.matroids.oriented_matroids', + 'oriented_matroids_catalog', 'oriented_matroids') From 6b34bcf72cd3d518acd4a241dc11a5372ad12589 Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 4 Jul 2023 10:33:58 +0100 Subject: [PATCH 012/101] Adding # keys --- oriented_matroids/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py index 6202b25..de07c45 100644 --- a/oriented_matroids/__init__.py +++ b/oriented_matroids/__init__.py @@ -3,5 +3,5 @@ from .oriented_matroids_category import OrientedMatroids from sage.misc.lazy_import import lazy_import -lazy_import('sage.matroids.oriented_matroids', - 'oriented_matroids_catalog', 'oriented_matroids') +#lazy_import('sage.matroids.oriented_matroids', + #'oriented_matroids_catalog', 'oriented_matroids') From a6c589beaf170fdae9cb6b1c55738464435b712f Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 4 Jul 2023 10:42:52 +0100 Subject: [PATCH 013/101] Removing # keys --- oriented_matroids/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py index de07c45..6202b25 100644 --- a/oriented_matroids/__init__.py +++ b/oriented_matroids/__init__.py @@ -3,5 +3,5 @@ from .oriented_matroids_category import OrientedMatroids from sage.misc.lazy_import import lazy_import -#lazy_import('sage.matroids.oriented_matroids', - #'oriented_matroids_catalog', 'oriented_matroids') +lazy_import('sage.matroids.oriented_matroids', + 'oriented_matroids_catalog', 'oriented_matroids') From 0c90fc5170e86b58f188e3c5ed6b5bc40613c9ec Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 4 Jul 2023 10:44:48 +0100 Subject: [PATCH 014/101] Added git add oriented_matroids/oriented_matroid.py to start line --- oriented_matroids/oriented_matroid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 0321e64..505d6d5 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- r""" -Oriented matroids construction +!!Oriented matroids construction Theory ====== From 53b3ebfd040052b76091451d7bd22fe1c23e9854 Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 4 Jul 2023 10:46:09 +0100 Subject: [PATCH 015/101] Removing the git add oriented_matroids/oriented_matroid.py from the start line --- oriented_matroids/oriented_matroid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 505d6d5..0321e64 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- r""" -!!Oriented matroids construction +Oriented matroids construction Theory ====== From c314416e6422d04b3c43bfc83b4d197894f72d3d Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 4 Jul 2023 12:42:12 +0100 Subject: [PATCH 016/101] Converted OM to a class and transferred the functions in category to make structure similar to matroids --- oriented_matroids/oriented_matroid.py | 512 ++++++++++++++++++++------ 1 file changed, 399 insertions(+), 113 deletions(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 0321e64..d64b673 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -44,7 +44,7 @@ import copy -def OrientedMatroid(data=None, groundset=None, key=None, **kwds): +class OrientedMatroid(SageObject): r""" Construct an oriented matroid. @@ -146,117 +146,403 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): For more information see [BLSWZ1999]_ . """ - - # Instantiate oriented matroid - OM = None - - # If we have a hyperplane arrangement we need to force the key to be an - # arrangement, - if isinstance(data, HyperplaneArrangementElement): - if key != 'covector' and key is not None: - raise ValueError( - 'Hyperplane arrangements are currently only implemented using covector axioms') - key = 'real_hyperplane_arrangement' - elif isinstance(data, PointConfiguration): - if key != 'circuit' and key is not None: - raise ValueError( - 'Point configurations are currently only implemented using circuit axioms') - key = 'circuit' - # PC circuits are given as (+, 0, -); and only half are given - ci = [(C[0], C[2], C[1]) for C in data.circuits()] - ci += [(C[2], C[0], C[1]) for C in data.circuits()] - data = ci - elif isinstance(data, DiGraph): - if key != 'circuit' and key is not None: - raise ValueError( - 'Digraphs are currently only implemented using circuit axioms') - key = 'circuit' - - # we need to add negative edges in order to do all simple cycles - digraph = copy.copy(data) - edges = copy.copy(list(digraph.edges())) - groundset = [] - if len(edges) != len(set(edges)): - raise ValueError('Edge labels need to be unique') - if None in digraph.edge_labels(): - raise ValueError('Edge labels must be set for all edges') - - # Add minus edges to properly get cycles - for e in edges: - digraph.add_edge(e[1], e[0], "NEG_"+str(e[2])) - groundset.append(str(e[2])) - # Each cycle defines a circuit - data = [] - for c in digraph.all_cycles_iterator(simple=True): - p = set([]) - n = set([]) - for e in range(len(c) - 1): - e = str(digraph.edge_label(c[e], c[e+1])) - if e.startswith('NEG_'): - n.add(e.strip('NEG_')) - else: - p.add(e) - # If an edge exists in both sets, then this is a false cycle. - # This implies we have ee^-1 which is why it's false. - # So we only add the true ones. - if len(p.intersection(n)) == 0: - data.append([p, n]) - elif isinstance(data, Matrix): - if key != 'chirotope' and key is not None: - raise ValueError( - 'Matrices are currently only implemented using chirotope axioms') - key = 'chirotope' - - if key not in OrientedMatroids.keys: - raise ValueError("invalid type key") - - # In the following cases, deep_tupler is used since we are using - # UniqueRepresentation Which doesn't allow us to have non-hashable things. - if key == "covector": - from oriented_matroids.covector_oriented_matroid \ - import CovectorOrientedMatroid - data = deep_tupler(data) - if groundset is not None: - groundset = deep_tupler(groundset) - OM = CovectorOrientedMatroid(data, groundset=groundset) - elif key == "circuit": - from oriented_matroids.circuit_oriented_matroid \ - import CircuitOrientedMatroid - data = deep_tupler(data) - if groundset is not None: - groundset = deep_tupler(groundset) - OM = CircuitOrientedMatroid(data, groundset=groundset) - elif key == "vector": - from oriented_matroids.vector_oriented_matroid \ - import VectorOrientedMatroid - data = deep_tupler(data) - if groundset is not None: + def is_valid(self): + r""" + Return whether satisfies oriented matroid axioms. + + Given a set of objects, this method tests against + a provided set of axioms for a given representation + to ensure that we actually do have an oriented matroid. + """ + pass + + def groundset(self): + """ + Return the ground set of ``self``. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: A = hyperplane_arrangements.braid(2) + sage: M = OrientedMatroid(A); M.groundset() + (Hyperplane t0 - t1 + 0,) + + """ + return self._groundset + + def elements(self): + """ + Return elements. + + The elements of an oriented matroid are the "defining" elements of + the oriented matroid. For example, covectors are the elements of + an oriented matroid defined using covectors. + """ + return self._elements + + def circuits(self): + """ + Return all circuits. + """ + if "_circuits" in dir(self): + return self._circuits + raise NotImplementedError("Circuits not implemented") + + def cocircuits(self): + """ + Return all cocircuits. + """ + if "_cocircuits" in dir(self): + return self._cocircuits + raise NotImplementedError("Cocircuits not implemented") + + def vectors(self): + """ + Return all vectors. + """ + if "_vectors" in dir(self): + return self._vectors + raise NotImplementedError("Vectors not implemented") + pass + + def covectors(self): + """ + Return all covectors. + """ + if "_covectors" in dir(self): + return self._covectors + raise NotImplementedError("Covectors not implemented") + + def to_circuit(self): + """ + Return circuit oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.circuits(), + key='circuit', + groundset=self.groundset()) + + def to_vector(self): + """ + Return vector oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.vectors(), + key='vector', + groundset=self.groundset()) + + def to_covector(self): + """ + Return covector oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.covectors(), + key='covector', + groundset=self.groundset()) + + def dual(self): + """ + Return the dual oriented matroid. + """ + pass + + def matroid(self): + r""" + Returns the underlying matroid. + """ + pass + + def rank(self): + r""" + Return the rank. + + The *rank* of an oriented matroid is the rank of its underlying + matroid. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: A = hyperplane_arrangements.braid(3) + sage: M = OrientedMatroid(A); M.rank() + 2 + sage: A = hyperplane_arrangements.braid(4) + sage: M = OrientedMatroid(A); M.rank() + 3 + """ + return self.matroid().rank() + + def an_element(self): + """ + Returns an arbitrary element. + """ + from sage.misc.prandom import randint + els = self.elements() + i = randint(1, len(els)) + return els[i-1] + + def face_poset(self, facade=False): + r""" + Returns the (big) face poset. + + The *(big) face poset* is the poset on covectors such that `X \leq Y` + if and only if `S(X,Y) = \emptyset` and + `\underline{Y} \subseteq \underline{X}`. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], + ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], + ....: [0,0,0]] + sage: M = OrientedMatroid(C, key='covector') + sage: M.face_poset() + Finite meet-semilattice containing 13 elements + """ + from sage.combinat.posets.lattices import MeetSemilattice + els = self.covectors() + rels = [ + (Y, X) + for X in els + for Y in els + if Y.is_conformal_with(X) and Y.support().issubset(X.support()) + ] + return MeetSemilattice((els, rels), cover_relations=False, facade=facade) + + def face_lattice(self, facade=False): + r""" + Returns the (big) face lattice. + + The *(big) face lattice* is the (big) face poset with a top element + added. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], + ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], + ....: [0,0,0]] + sage: M = OrientedMatroid(C, key='covector') + sage: M.face_lattice() + Finite lattice containing 14 elements + """ + from sage.combinat.posets.lattices import LatticePoset + els = self.covectors() + rels = [ + (Y, X) + for X in els + for Y in els + if Y.is_conformal_with(X) and Y.support().issubset(X.support()) + ] + + # Add top element + for i in els: + rels.append((i, 1)) + els.append(1) + return LatticePoset((els, rels), cover_relations=False, facade=facade) + +# P = self.face_poset() +# rels = P.relations() +# els = [1] +# for i in P: +# els.append(i.element) +# rels.append([i.element, 1]) +# +# return LatticePoset((els,rels), +# cover_relations=False, +# facade=facade) + + def topes(self): + r""" + Returns the topes. + + A *tope* is the maximal covector in the face poset. + """ + return self.face_poset(facade=True).maximal_elements() + + def tope_poset(self, base_tope, facade=False): + r""" + Returns the tope poset. + + The tope poset is the poset `(\mathcal{T}, B)` where `\mathcal{T}` + is the set of topes and `B` is a distinguished tope called the + *base tope*. The order is given by inclusion of separation sets + from the base tope: `X \leq Y` if and only if + `S(B, X) \subseteq S(B, Y)`. + """ + from sage.combinat.posets.posets import Poset + els = self.topes() + rels = [ + (X, Y) + for X in els + for Y in els + if base_tope.separation_set(X).issubset(base_tope.separation_set(Y)) + ] + + return Poset((els, rels), cover_relations=False, facade=facade) + + def is_simplicial(self): + r""" + Returns if the oriented matroid is simplicial. + + An oriented matroid is *simplicial* if every tope is simplicial. + + .. SEEALSO:: + + :meth:`~sage.matroids.oriented_matroids.signed_subset_element.SignedSubsetElement.is_simplicial` + """ + for t in self.topes(): + if not t.is_simplicial(): + return False + return True + + def is_acyclic(self): + r""" + Return if oriented matroid is acyclic. + + A covector oriented matroid is *acyclic* if there exists a positive + tope where a *positive tope* is defined as a tope with no + negative part. + """ + for t in self.topes(): + if len(t.negatives()) == 0: + return True + return False + + def deletion(self, change_set): + r""" + Returns a covector oriented matroid of a deletion. + + Let `M = (E, \mathcal{L})` be an oriented matroid over a set `E` + and a set of covectors `\mathcal{L}`. Given `A \subseteq E`, the + *deletion* is the (covector) oriented matroid + `M\backslash A = (E \backslash A, \mathcal{L} \backslash A)` where + + .. MATH:: + + \mathcal{C} \backslash A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C}\right\} + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + + """ + if change_set in self.groundset(): + change_set = set([change_set]) + else: + change_set = set(change_set) + + from oriented_matroids.oriented_matroid import deep_tupler + groundset = set(self.groundset()).difference(change_set) groundset = deep_tupler(groundset) - OM = VectorOrientedMatroid(data, groundset=groundset) - elif key == "real_hyperplane_arrangement": - from oriented_matroids.real_hyperplane_arrangement_oriented_matroid \ - import RealHyperplaneArrangementOrientedMatroid - A = copy.copy(data) - if groundset is None: - groundset = deep_tupler(A.hyperplanes()) - else: + data = [] + for c in self.covectors(): + p = tuple(c.positives().difference(change_set)) + n = tuple(c.negatives().difference(change_set)) + z = tuple(c.zeroes().difference(change_set)) + data.append((p, n, z)) + data = deep_tupler(data) + + from oriented_matroids import OrientedMatroid + return OrientedMatroid(data, key='covector', groundset=groundset) + + def restriction(self, change_set): + r""" + Returns a covector oriented matroid of a restriction. + + Given an oriented matroid `M = (E, \mathcal{L})` where `E` is a + set and `\mathcal{L}` is the set of covectors. Given + `A \subseteq E`, the *restriction* is the (covector) oriented + matroid `M / A = (E \backslash A, \mathcal{C} / A)` where + + .. MATH:: + + \mathcal{C} / A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C} \text{ and} A \subseteq X^0 \right\} + + """ + # sage: from oriented_matroids import OrientedMatroid + # sage: A = hyperplane_arrangements.braid(3) + # sage: M = OrientedMatroid(A); M + # Covector Oriented Matroid of rank 3 + # sage: R = M.restriction(M.groundset()[1]); R + # Covector Oriented Matroid of rank 2 + # sage: R.elements() + # [(0,0), (1,1), (-1,-1)] + if change_set in self.groundset(): + change_set = set([change_set]) + else: + change_set = set(change_set) + + from oriented_matroids.oriented_matroid import deep_tupler + groundset = set(self.groundset()).difference(change_set) groundset = deep_tupler(groundset) - OM = RealHyperplaneArrangementOrientedMatroid(A, groundset=groundset) - - if OM is None: - raise NotImplementedError( - "Oriented matroid of type {} is not implemented".format(key)) - - if OM.is_valid(): - return OM - - raise ValueError("Oriented matroid is not valid") - - -def deep_tupler(obj): - r""" - changes a (nested) list or set into a (nested) tuple to be hashable - """ - if isinstance(obj, list) or isinstance(obj, set): - return tuple([deep_tupler(i) for i in obj]) - return obj + data = [] + for c in self.covectors(): + p = tuple(c.positives().difference(change_set)) + n = tuple(c.negatives().difference(change_set)) + z = tuple(c.zeroes().difference(change_set)) + if change_set.issubset(c.zeroes()): + data.append((p, n, z)) + data = deep_tupler(data) + + from oriented_matroids import OrientedMatroid + return OrientedMatroid(data, key='covector', groundset=groundset) + + def loops(self): + r""" + Returns the loops of an oriented matroid. + + A *loop* is an element `e \in E` such that there is a + tope `T \in \mathcal{T}` with `T(e) = 0`. In particular + if `T(e) = 0` for some `T`, then it is true for all + `T \in \mathcal{T}`. + """ + T = self.topes()[0] + loops = [] + gs = self.groundset() + for i, j in enumerate(T): + if T(j) == 0: + loops.append(gs[i]) + return loops + + def are_parallel(self, e, f): + r""" + Returns whether two elements in ground set are parallel. + + Two elements in the ground set `e, f \in E` are parallel if they + are not loops and for all `X \in \mathcal{C}`, `X(e) = 0` + implies `X(f) = 0`. See Lemma 4.1.10 [BLSWZ1999]_ . + """ + gs = set(self.groundset()).difference(set(self.loops())) + if e not in gs or f not in gs: + raise ValueError( + "Elements must be in groundset and must not be loops") + for i in self.elements(): + if i(e) == 0 and i(f) != 0: + return False + return True + + def is_simple(self): + r""" + Returns if the oriented matroid is simple. + + An oriented matroid is *simple* if there are no loops + and no parallel elements. + """ + from sage.combinat.subset import Subsets + if len(self.loops()) > 0: + return False + for i in Subsets(self.groundset(), 2): + if self.are_parallel(i[0], i[1]): + return False + return True + + def _element_constructor_(self, x): + r""" + Determine if ``x`` may be viewed as belonging to ``self``. + """ + try: + if x in self.elements(): + return x + return False + except ValueError: + return False \ No newline at end of file From a1f96bf99a6621c2b1b5e7a6af0775bf3ba91b96 Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 4 Jul 2023 13:55:06 +0100 Subject: [PATCH 017/101] Fixing indentation --- oriented_matroids/oriented_matroid.py | 594 +++++++++++++------------- 1 file changed, 297 insertions(+), 297 deletions(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index d64b673..7003b9b 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -147,198 +147,198 @@ class OrientedMatroid(SageObject): """ def is_valid(self): - r""" - Return whether satisfies oriented matroid axioms. - - Given a set of objects, this method tests against - a provided set of axioms for a given representation - to ensure that we actually do have an oriented matroid. - """ - pass + r""" + Return whether satisfies oriented matroid axioms. + + Given a set of objects, this method tests against + a provided set of axioms for a given representation + to ensure that we actually do have an oriented matroid. + """ + pass def groundset(self): - """ - Return the ground set of ``self``. + """ + Return the ground set of ``self``. - EXAMPLES:: + EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid - sage: A = hyperplane_arrangements.braid(2) - sage: M = OrientedMatroid(A); M.groundset() - (Hyperplane t0 - t1 + 0,) + sage: from oriented_matroids import OrientedMatroid + sage: A = hyperplane_arrangements.braid(2) + sage: M = OrientedMatroid(A); M.groundset() + (Hyperplane t0 - t1 + 0,) - """ - return self._groundset + """ + return self._groundset def elements(self): - """ - Return elements. - - The elements of an oriented matroid are the "defining" elements of - the oriented matroid. For example, covectors are the elements of - an oriented matroid defined using covectors. - """ - return self._elements + """ + Return elements. + + The elements of an oriented matroid are the "defining" elements of + the oriented matroid. For example, covectors are the elements of + an oriented matroid defined using covectors. + """ + return self._elements def circuits(self): - """ - Return all circuits. - """ - if "_circuits" in dir(self): - return self._circuits - raise NotImplementedError("Circuits not implemented") + """ + Return all circuits. + """ + if "_circuits" in dir(self): + return self._circuits + raise NotImplementedError("Circuits not implemented") def cocircuits(self): - """ - Return all cocircuits. - """ - if "_cocircuits" in dir(self): - return self._cocircuits - raise NotImplementedError("Cocircuits not implemented") + """ + Return all cocircuits. + """ + if "_cocircuits" in dir(self): + return self._cocircuits + raise NotImplementedError("Cocircuits not implemented") def vectors(self): - """ - Return all vectors. - """ - if "_vectors" in dir(self): - return self._vectors - raise NotImplementedError("Vectors not implemented") - pass + """ + Return all vectors. + """ + if "_vectors" in dir(self): + return self._vectors + raise NotImplementedError("Vectors not implemented") + pass def covectors(self): - """ - Return all covectors. - """ - if "_covectors" in dir(self): - return self._covectors - raise NotImplementedError("Covectors not implemented") + """ + Return all covectors. + """ + if "_covectors" in dir(self): + return self._covectors + raise NotImplementedError("Covectors not implemented") def to_circuit(self): - """ - Return circuit oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.circuits(), + """ + Return circuit oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.circuits(), key='circuit', groundset=self.groundset()) def to_vector(self): - """ - Return vector oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.vectors(), + """ + Return vector oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.vectors(), key='vector', groundset=self.groundset()) def to_covector(self): - """ - Return covector oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.covectors(), + """ + Return covector oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.covectors(), key='covector', groundset=self.groundset()) def dual(self): - """ - Return the dual oriented matroid. - """ - pass + """ + Return the dual oriented matroid. + """ + pass def matroid(self): - r""" - Returns the underlying matroid. - """ - pass + r""" + Returns the underlying matroid. + """ + pass def rank(self): - r""" - Return the rank. + r""" + Return the rank. - The *rank* of an oriented matroid is the rank of its underlying - matroid. + The *rank* of an oriented matroid is the rank of its underlying + matroid. - EXAMPLES:: + EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid - sage: A = hyperplane_arrangements.braid(3) - sage: M = OrientedMatroid(A); M.rank() - 2 - sage: A = hyperplane_arrangements.braid(4) - sage: M = OrientedMatroid(A); M.rank() - 3 - """ - return self.matroid().rank() + sage: from oriented_matroids import OrientedMatroid + sage: A = hyperplane_arrangements.braid(3) + sage: M = OrientedMatroid(A); M.rank() + 2 + sage: A = hyperplane_arrangements.braid(4) + sage: M = OrientedMatroid(A); M.rank() + 3 + """ + return self.matroid().rank() def an_element(self): - """ - Returns an arbitrary element. - """ - from sage.misc.prandom import randint - els = self.elements() - i = randint(1, len(els)) - return els[i-1] + """ + Returns an arbitrary element. + """ + from sage.misc.prandom import randint + els = self.elements() + i = randint(1, len(els)) + return els[i-1] def face_poset(self, facade=False): - r""" - Returns the (big) face poset. - - The *(big) face poset* is the poset on covectors such that `X \leq Y` - if and only if `S(X,Y) = \emptyset` and - `\underline{Y} \subseteq \underline{X}`. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], - ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], - ....: [0,0,0]] - sage: M = OrientedMatroid(C, key='covector') - sage: M.face_poset() - Finite meet-semilattice containing 13 elements - """ - from sage.combinat.posets.lattices import MeetSemilattice - els = self.covectors() - rels = [ - (Y, X) - for X in els - for Y in els - if Y.is_conformal_with(X) and Y.support().issubset(X.support()) + r""" + Returns the (big) face poset. + + The *(big) face poset* is the poset on covectors such that `X \leq Y` + if and only if `S(X,Y) = \emptyset` and + `\underline{Y} \subseteq \underline{X}`. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], + ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], + ....: [0,0,0]] + sage: M = OrientedMatroid(C, key='covector') + sage: M.face_poset() + Finite meet-semilattice containing 13 elements + """ + from sage.combinat.posets.lattices import MeetSemilattice + els = self.covectors() + rels = [ + (Y, X) + for X in els + for Y in els + if Y.is_conformal_with(X) and Y.support().issubset(X.support()) ] - return MeetSemilattice((els, rels), cover_relations=False, facade=facade) + return MeetSemilattice((els, rels), cover_relations=False, facade=facade) def face_lattice(self, facade=False): - r""" - Returns the (big) face lattice. - - The *(big) face lattice* is the (big) face poset with a top element - added. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], - ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], - ....: [0,0,0]] - sage: M = OrientedMatroid(C, key='covector') - sage: M.face_lattice() - Finite lattice containing 14 elements - """ - from sage.combinat.posets.lattices import LatticePoset - els = self.covectors() - rels = [ - (Y, X) - for X in els - for Y in els - if Y.is_conformal_with(X) and Y.support().issubset(X.support()) + r""" + Returns the (big) face lattice. + + The *(big) face lattice* is the (big) face poset with a top element + added. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], + ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], + ....: [0,0,0]] + sage: M = OrientedMatroid(C, key='covector') + sage: M.face_lattice() + Finite lattice containing 14 elements + """ + from sage.combinat.posets.lattices import LatticePoset + els = self.covectors() + rels = [ + (Y, X) + for X in els + for Y in els + if Y.is_conformal_with(X) and Y.support().issubset(X.support()) ] - # Add top element - for i in els: - rels.append((i, 1)) - els.append(1) - return LatticePoset((els, rels), cover_relations=False, facade=facade) + # Add top element + for i in els: + rels.append((i, 1)) + els.append(1) + return LatticePoset((els, rels), cover_relations=False, facade=facade) # P = self.face_poset() # rels = P.relations() @@ -352,113 +352,113 @@ def face_lattice(self, facade=False): # facade=facade) def topes(self): - r""" - Returns the topes. + r""" + Returns the topes. - A *tope* is the maximal covector in the face poset. - """ - return self.face_poset(facade=True).maximal_elements() + A *tope* is the maximal covector in the face poset. + """ + return self.face_poset(facade=True).maximal_elements() def tope_poset(self, base_tope, facade=False): - r""" - Returns the tope poset. - - The tope poset is the poset `(\mathcal{T}, B)` where `\mathcal{T}` - is the set of topes and `B` is a distinguished tope called the - *base tope*. The order is given by inclusion of separation sets - from the base tope: `X \leq Y` if and only if - `S(B, X) \subseteq S(B, Y)`. - """ - from sage.combinat.posets.posets import Poset - els = self.topes() - rels = [ - (X, Y) - for X in els - for Y in els - if base_tope.separation_set(X).issubset(base_tope.separation_set(Y)) + r""" + Returns the tope poset. + + The tope poset is the poset `(\mathcal{T}, B)` where `\mathcal{T}` + is the set of topes and `B` is a distinguished tope called the + *base tope*. The order is given by inclusion of separation sets + from the base tope: `X \leq Y` if and only if + `S(B, X) \subseteq S(B, Y)`. + """ + from sage.combinat.posets.posets import Poset + els = self.topes() + rels = [ + (X, Y) + for X in els + for Y in els + if base_tope.separation_set(X).issubset(base_tope.separation_set(Y)) ] - return Poset((els, rels), cover_relations=False, facade=facade) + return Poset((els, rels), cover_relations=False, facade=facade) def is_simplicial(self): - r""" - Returns if the oriented matroid is simplicial. + r""" + Returns if the oriented matroid is simplicial. - An oriented matroid is *simplicial* if every tope is simplicial. + An oriented matroid is *simplicial* if every tope is simplicial. - .. SEEALSO:: + .. SEEALSO:: - :meth:`~sage.matroids.oriented_matroids.signed_subset_element.SignedSubsetElement.is_simplicial` - """ - for t in self.topes(): - if not t.is_simplicial(): - return False - return True + :meth:`~sage.matroids.oriented_matroids.signed_subset_element.SignedSubsetElement.is_simplicial` + """ + for t in self.topes(): + if not t.is_simplicial(): + return False + return True def is_acyclic(self): - r""" - Return if oriented matroid is acyclic. - - A covector oriented matroid is *acyclic* if there exists a positive - tope where a *positive tope* is defined as a tope with no - negative part. - """ - for t in self.topes(): - if len(t.negatives()) == 0: - return True - return False + r""" + Return if oriented matroid is acyclic. + + A covector oriented matroid is *acyclic* if there exists a positive + tope where a *positive tope* is defined as a tope with no + negative part. + """ + for t in self.topes(): + if len(t.negatives()) == 0: + return True + return False def deletion(self, change_set): - r""" - Returns a covector oriented matroid of a deletion. + r""" + Returns a covector oriented matroid of a deletion. - Let `M = (E, \mathcal{L})` be an oriented matroid over a set `E` - and a set of covectors `\mathcal{L}`. Given `A \subseteq E`, the - *deletion* is the (covector) oriented matroid - `M\backslash A = (E \backslash A, \mathcal{L} \backslash A)` where + Let `M = (E, \mathcal{L})` be an oriented matroid over a set `E` + and a set of covectors `\mathcal{L}`. Given `A \subseteq E`, the + *deletion* is the (covector) oriented matroid + `M\backslash A = (E \backslash A, \mathcal{L} \backslash A)` where - .. MATH:: + .. MATH:: - \mathcal{C} \backslash A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C}\right\} + \mathcal{C} \backslash A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C}\right\} - EXAMPLES:: + EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids import OrientedMatroid - """ - if change_set in self.groundset(): - change_set = set([change_set]) - else: - change_set = set(change_set) - - from oriented_matroids.oriented_matroid import deep_tupler - groundset = set(self.groundset()).difference(change_set) - groundset = deep_tupler(groundset) - data = [] - for c in self.covectors(): - p = tuple(c.positives().difference(change_set)) - n = tuple(c.negatives().difference(change_set)) - z = tuple(c.zeroes().difference(change_set)) - data.append((p, n, z)) - data = deep_tupler(data) + """ + if change_set in self.groundset(): + change_set = set([change_set]) + else: + change_set = set(change_set) + + from oriented_matroids.oriented_matroid import deep_tupler + groundset = set(self.groundset()).difference(change_set) + groundset = deep_tupler(groundset) + data = [] + for c in self.covectors(): + p = tuple(c.positives().difference(change_set)) + n = tuple(c.negatives().difference(change_set)) + z = tuple(c.zeroes().difference(change_set)) + data.append((p, n, z)) + data = deep_tupler(data) - from oriented_matroids import OrientedMatroid - return OrientedMatroid(data, key='covector', groundset=groundset) + from oriented_matroids import OrientedMatroid + return OrientedMatroid(data, key='covector', groundset=groundset) def restriction(self, change_set): - r""" - Returns a covector oriented matroid of a restriction. + r""" + Returns a covector oriented matroid of a restriction. - Given an oriented matroid `M = (E, \mathcal{L})` where `E` is a - set and `\mathcal{L}` is the set of covectors. Given - `A \subseteq E`, the *restriction* is the (covector) oriented - matroid `M / A = (E \backslash A, \mathcal{C} / A)` where + Given an oriented matroid `M = (E, \mathcal{L})` where `E` is a + set and `\mathcal{L}` is the set of covectors. Given + `A \subseteq E`, the *restriction* is the (covector) oriented + matroid `M / A = (E \backslash A, \mathcal{C} / A)` where - .. MATH:: + .. MATH:: - \mathcal{C} / A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C} \text{ and} A \subseteq X^0 \right\} + \mathcal{C} / A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C} \text{ and} A \subseteq X^0 \right\} - """ + """ # sage: from oriented_matroids import OrientedMatroid # sage: A = hyperplane_arrangements.braid(3) # sage: M = OrientedMatroid(A); M @@ -467,82 +467,82 @@ def restriction(self, change_set): # Covector Oriented Matroid of rank 2 # sage: R.elements() # [(0,0), (1,1), (-1,-1)] - if change_set in self.groundset(): - change_set = set([change_set]) - else: - change_set = set(change_set) - - from oriented_matroids.oriented_matroid import deep_tupler - groundset = set(self.groundset()).difference(change_set) - groundset = deep_tupler(groundset) - data = [] - for c in self.covectors(): - p = tuple(c.positives().difference(change_set)) - n = tuple(c.negatives().difference(change_set)) - z = tuple(c.zeroes().difference(change_set)) - if change_set.issubset(c.zeroes()): - data.append((p, n, z)) - data = deep_tupler(data) - - from oriented_matroids import OrientedMatroid - return OrientedMatroid(data, key='covector', groundset=groundset) + if change_set in self.groundset(): + change_set = set([change_set]) + else: + change_set = set(change_set) + + from oriented_matroids.oriented_matroid import deep_tupler + groundset = set(self.groundset()).difference(change_set) + groundset = deep_tupler(groundset) + data = [] + for c in self.covectors(): + p = tuple(c.positives().difference(change_set)) + n = tuple(c.negatives().difference(change_set)) + z = tuple(c.zeroes().difference(change_set)) + if change_set.issubset(c.zeroes()): + data.append((p, n, z)) + data = deep_tupler(data) + + from oriented_matroids import OrientedMatroid + return OrientedMatroid(data, key='covector', groundset=groundset) def loops(self): - r""" - Returns the loops of an oriented matroid. - - A *loop* is an element `e \in E` such that there is a - tope `T \in \mathcal{T}` with `T(e) = 0`. In particular - if `T(e) = 0` for some `T`, then it is true for all - `T \in \mathcal{T}`. - """ - T = self.topes()[0] - loops = [] - gs = self.groundset() - for i, j in enumerate(T): - if T(j) == 0: - loops.append(gs[i]) - return loops + r""" + Returns the loops of an oriented matroid. + + A *loop* is an element `e \in E` such that there is a + tope `T \in \mathcal{T}` with `T(e) = 0`. In particular + if `T(e) = 0` for some `T`, then it is true for all + `T \in \mathcal{T}`. + """ + T = self.topes()[0] + loops = [] + gs = self.groundset() + for i, j in enumerate(T): + if T(j) == 0: + loops.append(gs[i]) + return loops def are_parallel(self, e, f): - r""" - Returns whether two elements in ground set are parallel. - - Two elements in the ground set `e, f \in E` are parallel if they - are not loops and for all `X \in \mathcal{C}`, `X(e) = 0` - implies `X(f) = 0`. See Lemma 4.1.10 [BLSWZ1999]_ . - """ - gs = set(self.groundset()).difference(set(self.loops())) - if e not in gs or f not in gs: - raise ValueError( - "Elements must be in groundset and must not be loops") - for i in self.elements(): - if i(e) == 0 and i(f) != 0: - return False - return True + r""" + Returns whether two elements in ground set are parallel. + + Two elements in the ground set `e, f \in E` are parallel if they + are not loops and for all `X \in \mathcal{C}`, `X(e) = 0` + implies `X(f) = 0`. See Lemma 4.1.10 [BLSWZ1999]_ . + """ + gs = set(self.groundset()).difference(set(self.loops())) + if e not in gs or f not in gs: + raise ValueError( + "Elements must be in groundset and must not be loops") + for i in self.elements(): + if i(e) == 0 and i(f) != 0: + return False + return True def is_simple(self): - r""" - Returns if the oriented matroid is simple. - - An oriented matroid is *simple* if there are no loops - and no parallel elements. - """ - from sage.combinat.subset import Subsets - if len(self.loops()) > 0: + r""" + Returns if the oriented matroid is simple. + + An oriented matroid is *simple* if there are no loops + and no parallel elements. + """ + from sage.combinat.subset import Subsets + if len(self.loops()) > 0: + return False + for i in Subsets(self.groundset(), 2): + if self.are_parallel(i[0], i[1]): return False - for i in Subsets(self.groundset(), 2): - if self.are_parallel(i[0], i[1]): - return False - return True + return True def _element_constructor_(self, x): - r""" - Determine if ``x`` may be viewed as belonging to ``self``. - """ - try: - if x in self.elements(): - return x - return False - except ValueError: - return False \ No newline at end of file + r""" + Determine if ``x`` may be viewed as belonging to ``self``. + """ + try: + if x in self.elements(): + return x + return False + except ValueError: + return False \ No newline at end of file From 255af0d0b4ef96ad0c0c319f68b8c5174248896e Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 07:38:43 +0100 Subject: [PATCH 018/101] Changing the inheritance and importing OM --- oriented_matroids/circuit_oriented_matroid.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index eb562dd..484e345 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -23,9 +23,10 @@ from sage.structure.parent import Parent from oriented_matroids.oriented_matroids_category import OrientedMatroids from oriented_matroids.signed_subset_element import SignedSubsetElement +from oriented_matroids.oriented_matroid import OrientedMatroid -class CircuitOrientedMatroid(UniqueRepresentation, Parent): +class CircuitOrientedMatroid(OrientedMatroid): r""" An oriented matroid implemented using circuit axioms. From 4e6078ef1fa56902f3dae8b24feb77f703e3cb0f Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 07:50:23 +0100 Subject: [PATCH 019/101] Importing SageObject --- oriented_matroids/oriented_matroid.py | 1 + 1 file changed, 1 insertion(+) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 7003b9b..dfbec98 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -42,6 +42,7 @@ from sage.structure.element import Matrix from oriented_matroids.oriented_matroids_category import OrientedMatroids import copy +from sage.structure.sage_object import SageObject class OrientedMatroid(SageObject): From f20c6482d45aa1779190962ade3661b60cecb5fe Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 08:26:01 +0100 Subject: [PATCH 020/101] Removing category from __classcall__ --- oriented_matroids/circuit_oriented_matroid.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 484e345..65a7b1d 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -78,12 +78,10 @@ def __classcall__(cls, data, groundset=None): Normalize arguments and set class. """ - category = OrientedMatroids() return super(CircuitOrientedMatroid, cls) \ .__classcall__(cls, data=data, - groundset=groundset, - category=category) + groundset=groundset) def __init__(self, data, groundset=None, category=None): """ From 4305d4835c841f06f49f3b6877056a16cb6b8b00 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 09:54:46 +0100 Subject: [PATCH 021/101] Removed importing UniqueRepresentation --- oriented_matroids/circuit_oriented_matroid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 65a7b1d..2114ca0 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -19,7 +19,7 @@ # http://www.gnu.org/licenses/ ############################################################################## -from sage.structure.unique_representation import UniqueRepresentation + from sage.structure.parent import Parent from oriented_matroids.oriented_matroids_category import OrientedMatroids from oriented_matroids.signed_subset_element import SignedSubsetElement From a1944411a2c138d7358993f6178d355005077f38 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 09:56:44 +0100 Subject: [PATCH 022/101] Removed importing from oriented_matroids_category --- oriented_matroids/circuit_oriented_matroid.py | 1 - 1 file changed, 1 deletion(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 2114ca0..0797e80 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -21,7 +21,6 @@ from sage.structure.parent import Parent -from oriented_matroids.oriented_matroids_category import OrientedMatroids from oriented_matroids.signed_subset_element import SignedSubsetElement from oriented_matroids.oriented_matroid import OrientedMatroid From 979bf44f3e0f92b8e6718c4e43fc08335d6eb8bd Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 10:15:59 +0100 Subject: [PATCH 023/101] Removing category from __init__ function --- oriented_matroids/circuit_oriented_matroid.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 0797e80..d65b0e8 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -82,11 +82,10 @@ def __classcall__(cls, data, groundset=None): data=data, groundset=groundset) - def __init__(self, data, groundset=None, category=None): + def __init__(self, data, groundset=None): """ Initialize ``self``. """ - Parent.__init__(self, category=category) # Set up our circuits circuits = [] From 69c24458a9d8c638d961a1ed613c554dd658b3ad Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 10:30:10 +0100 Subject: [PATCH 024/101] Removing importing parent --- oriented_matroids/circuit_oriented_matroid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index d65b0e8..615b626 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -20,7 +20,7 @@ ############################################################################## -from sage.structure.parent import Parent + from oriented_matroids.signed_subset_element import SignedSubsetElement from oriented_matroids.oriented_matroid import OrientedMatroid From 828a4ae2ad72abe30840c5f787c91b3deceb5686 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 10:44:25 +0100 Subject: [PATCH 025/101] Removing _ from self._groundset in groundset function --- oriented_matroids/oriented_matroid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index dfbec98..7aa3f61 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -169,7 +169,7 @@ def groundset(self): (Hyperplane t0 - t1 + 0,) """ - return self._groundset + return self.groundset def elements(self): """ From 33c26d685d8711e7458b87bb1d2a6d0d47d2c2ac Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 14:52:10 +0100 Subject: [PATCH 026/101] Adding back in _ for groundset function --- oriented_matroids/oriented_matroid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 7aa3f61..dfbec98 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -169,7 +169,7 @@ def groundset(self): (Hyperplane t0 - t1 + 0,) """ - return self.groundset + return self._groundset def elements(self): """ From 7d7266b82058822353ed365ca47f44733ed05ab4 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 15:01:50 +0100 Subject: [PATCH 027/101] Changing class inheritance and importing OrientedMatroid --- oriented_matroids/covector_oriented_matroid.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 7a08dda..8336a53 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -23,11 +23,12 @@ from sage.structure.parent import Parent from oriented_matroids.oriented_matroids_category import OrientedMatroids from oriented_matroids.signed_vector_element import SignedVectorElement +from oriented_matroids.oriented_matroid import OrientedMatroid import copy -class CovectorOrientedMatroid(UniqueRepresentation, Parent): +class CovectorOrientedMatroid(OrientedMatroid): r""" An oriented matroid implemented using covector axioms. From b402551e08269cc12649a9e26b36bf0004f7023a Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 15:03:56 +0100 Subject: [PATCH 028/101] Removing Imported UniqueRepresentation --- oriented_matroids/covector_oriented_matroid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 8336a53..fffd99c 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -19,7 +19,7 @@ # http://www.gnu.org/licenses/ ############################################################################## -from sage.structure.unique_representation import UniqueRepresentation + from sage.structure.parent import Parent from oriented_matroids.oriented_matroids_category import OrientedMatroids from oriented_matroids.signed_vector_element import SignedVectorElement From 22015d4e91eded1345a425b6046352288b93f307 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 15:08:36 +0100 Subject: [PATCH 029/101] Removing category from __classcall__ function --- oriented_matroids/covector_oriented_matroid.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index fffd99c..4fa660e 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -84,14 +84,13 @@ class CovectorOrientedMatroid(OrientedMatroid): Element = SignedVectorElement @staticmethod - def __classcall__(cls, data, groundset=None, category=None): + def __classcall__(cls, data, groundset=None): """ Normalize arguments and set class. """ - if category is None: - category = OrientedMatroids() + return super(CovectorOrientedMatroid, cls) \ - .__classcall__(cls, data, groundset=groundset, category=category) + .__classcall__(cls, data, groundset=groundset) def __init__(self, data, groundset=None, category=None): """ From c590a1c935fe0a9e857a4603a36ba49100264c3a Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 15:16:13 +0100 Subject: [PATCH 030/101] Removing category from __init__ function --- oriented_matroids/covector_oriented_matroid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 4fa660e..48f9f74 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -92,11 +92,11 @@ def __classcall__(cls, data, groundset=None): return super(CovectorOrientedMatroid, cls) \ .__classcall__(cls, data, groundset=groundset) - def __init__(self, data, groundset=None, category=None): + def __init__(self, data, groundset=None): """ Initialize ``self`` """ - Parent.__init__(self, category=category) + Parent.__init__(self) # Set up our covectors covectors = [] From a90c9b8289c7e06ae1c787f0c274e38a1d47a4c2 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 15:29:37 +0100 Subject: [PATCH 031/101] Removing importing categories --- oriented_matroids/covector_oriented_matroid.py | 1 - 1 file changed, 1 deletion(-) diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 48f9f74..6b78bde 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -21,7 +21,6 @@ from sage.structure.parent import Parent -from oriented_matroids.oriented_matroids_category import OrientedMatroids from oriented_matroids.signed_vector_element import SignedVectorElement from oriented_matroids.oriented_matroid import OrientedMatroid From 2a8f48ca2c1938fdf23cd38735c4f9bf66eeae30 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 15:55:27 +0100 Subject: [PATCH 032/101] Removing category from __classcall__ function --- .../real_hyperplane_arrangement_oriented_matroid.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index 942e1b2..70f5af9 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -21,7 +21,7 @@ from sage.structure.parent import Parent from oriented_matroids.covector_oriented_matroid import CovectorOrientedMatroid -from oriented_matroids.oriented_matroids_category import OrientedMatroids + class RealHyperplaneArrangementOrientedMatroid(CovectorOrientedMatroid): r""" @@ -64,17 +64,15 @@ class RealHyperplaneArrangementOrientedMatroid(CovectorOrientedMatroid): """ @staticmethod - def __classcall__(cls, data, groundset=None, category=None): + def __classcall__(cls, data, groundset=None): """ Normalize arguments and set class. """ - if category is None: - category = OrientedMatroids() + return super(RealHyperplaneArrangementOrientedMatroid, cls) \ .__classcall__(cls, data=data, - groundset=groundset, - category=category) + groundset=groundset) def __init__(self, data, groundset=None, category=None): """ From 8d55f8c1ba463dffac222e17b0a631569c5cb7c7 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 15:58:23 +0100 Subject: [PATCH 033/101] Removing category from the __init__ --- .../real_hyperplane_arrangement_oriented_matroid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index 70f5af9..b0fc481 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -74,11 +74,11 @@ def __classcall__(cls, data, groundset=None): data=data, groundset=groundset) - def __init__(self, data, groundset=None, category=None): + def __init__(self, data, groundset=None): """ Initialize ``self`` """ - Parent.__init__(self, category=category) + Parent.__init__(self) self._arrangement = data From c1cc5dbeb723e87df886960946d46d2af573fedd Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 16:12:26 +0100 Subject: [PATCH 034/101] Changing class inheritance to OrientedMatroid, importing it and removing UR import --- oriented_matroids/vector_oriented_matroid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index 93ed952..d4984f5 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -19,13 +19,13 @@ # http://www.gnu.org/licenses/ ############################################################################## -from sage.structure.unique_representation import UniqueRepresentation +from oriented_matroids.oriented_matriod import OrientedMatroid from sage.structure.parent import Parent from oriented_matroids import OrientedMatroids from oriented_matroids.signed_vector_element import SignedVectorElement -class VectorOrientedMatroid(UniqueRepresentation, Parent): +class VectorOrientedMatroid(OrientedMatroid): r""" An oriented matroid implemented using vector axioms. From 0fc19beb9d752973c23f6365fbd623e15bc8f331 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 16:16:05 +0100 Subject: [PATCH 035/101] Removing category from __classcall__ function --- oriented_matroids/vector_oriented_matroid.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index d4984f5..08a0076 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -81,9 +81,8 @@ def __classcall__(cls, data, groundset=None): """ Normalize arguments and set class. """ - category = OrientedMatroids() return super(VectorOrientedMatroid, cls) \ - .__classcall__(cls, data, groundset=groundset, category=category) + .__classcall__(cls, data, groundset=groundset) def __init__(self, data, groundset=None, category=None): """ From 51657e499aea629feec688f10fd77fbf7f3ea3f6 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 5 Jul 2023 16:17:31 +0100 Subject: [PATCH 036/101] Removing category from __init__ function --- oriented_matroids/vector_oriented_matroid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index 08a0076..b366365 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -84,11 +84,11 @@ def __classcall__(cls, data, groundset=None): return super(VectorOrientedMatroid, cls) \ .__classcall__(cls, data, groundset=groundset) - def __init__(self, data, groundset=None, category=None): + def __init__(self, data, groundset=None): """ Initialize ``self``. """ - Parent.__init__(self, category=category) + Parent.__init__(self) # Set up our vectors vectors = [] From 9d70b9d58135bf48f0cf83bc7b638658a51ce7a4 Mon Sep 17 00:00:00 2001 From: lizzy Date: Fri, 7 Jul 2023 09:02:29 +0100 Subject: [PATCH 037/101] Removing importing OrientedMatroids --- oriented_matroids/vector_oriented_matroid.py | 1 - 1 file changed, 1 deletion(-) diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index b366365..41eb71c 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -21,7 +21,6 @@ from oriented_matroids.oriented_matriod import OrientedMatroid from sage.structure.parent import Parent -from oriented_matroids import OrientedMatroids from oriented_matroids.signed_vector_element import SignedVectorElement From e48ed33967b0ef55aef90e379771a72fbf95a0fb Mon Sep 17 00:00:00 2001 From: lizzy Date: Fri, 7 Jul 2023 09:26:27 +0100 Subject: [PATCH 038/101] Changing the groundset funtion to be similar to the matroid one --- oriented_matroids/oriented_matroid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index dfbec98..41d80be 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -169,7 +169,7 @@ def groundset(self): (Hyperplane t0 - t1 + 0,) """ - return self._groundset + raise NotImplementedError("subclasses need to implement this.") def elements(self): """ From f1072925a4b7ec1b72653296468b854937c6c95a Mon Sep 17 00:00:00 2001 From: lizzy Date: Fri, 7 Jul 2023 09:27:54 +0100 Subject: [PATCH 039/101] Changing the groundset function --- oriented_matroids/circuit_oriented_matroid.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 615b626..6258c9f 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -111,6 +111,15 @@ def __init__(self, data, groundset=None): self._groundset = None else: self._groundset = tuple(groundset) + + def groundset(self): + """ + Return the ground set of ``self``. + + EXAMPLES:: + + """ + return self._groundset def is_valid(self): """ From 7807b7ffe812e3bfe4b843bcd4979f57bcc191ee Mon Sep 17 00:00:00 2001 From: lizzy Date: Fri, 7 Jul 2023 09:54:00 +0100 Subject: [PATCH 040/101] Testing groundset function --- .../real_hyperplane_arrangement_oriented_matroid.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index b0fc481..8548716 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -95,6 +95,9 @@ def __init__(self, data, groundset=None): self._covectors = [self.element_class( self, data=f, groundset=self._groundset) for f in faces] self._elements = self._covectors + + def groundset(self): + return self._groundset def _repr_(self): """ From 20673aa27d6112c7bcfd4e23280af3028fc9cee7 Mon Sep 17 00:00:00 2001 From: lizzy Date: Fri, 7 Jul 2023 10:07:01 +0100 Subject: [PATCH 041/101] Changing groundset back to normal --- oriented_matroids/oriented_matroid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 41d80be..dfbec98 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -169,7 +169,7 @@ def groundset(self): (Hyperplane t0 - t1 + 0,) """ - raise NotImplementedError("subclasses need to implement this.") + return self._groundset def elements(self): """ From 4a435fced8d7913d732e2c9c1b9633adbc64029a Mon Sep 17 00:00:00 2001 From: lizzy Date: Fri, 7 Jul 2023 10:08:17 +0100 Subject: [PATCH 042/101] Removing groundset function --- .../real_hyperplane_arrangement_oriented_matroid.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index 8548716..b0fc481 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -95,9 +95,6 @@ def __init__(self, data, groundset=None): self._covectors = [self.element_class( self, data=f, groundset=self._groundset) for f in faces] self._elements = self._covectors - - def groundset(self): - return self._groundset def _repr_(self): """ From 5be1cf5217d2357e89b49dd2c9ec3db4910ca817 Mon Sep 17 00:00:00 2001 From: lizzy Date: Fri, 7 Jul 2023 10:10:25 +0100 Subject: [PATCH 043/101] Deleting groundset function --- oriented_matroids/circuit_oriented_matroid.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 6258c9f..615b626 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -111,15 +111,6 @@ def __init__(self, data, groundset=None): self._groundset = None else: self._groundset = tuple(groundset) - - def groundset(self): - """ - Return the ground set of ``self``. - - EXAMPLES:: - - """ - return self._groundset def is_valid(self): """ From 245af0382f8afbd9b74a054bc98bf404606cdce3 Mon Sep 17 00:00:00 2001 From: lizzy Date: Sat, 8 Jul 2023 10:25:57 +0100 Subject: [PATCH 044/101] Adding constructor file --- oriented_matroids/constructor.py | 262 +++++++++++++++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 oriented_matroids/constructor.py diff --git a/oriented_matroids/constructor.py b/oriented_matroids/constructor.py new file mode 100644 index 0000000..76aa607 --- /dev/null +++ b/oriented_matroids/constructor.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 -*- +r""" +Oriented matroids construction + +Theory +====== + +Oriented matroids are ... + +Built-in oriented matroids +========================== + +... + +Constructing oriented matroids +============================== + +To define your own oriented matroid,... + + +AUTHORS: + +- Aram Dermenjian (2019-07-12): initial version + +""" + +# ***************************************************************************** +# Copyright (C) 2019 Aram Dermenjian +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +# ***************************************************************************** + +from sage.geometry.hyperplane_arrangement.arrangement \ + import HyperplaneArrangementElement +from sage.geometry.triangulation.point_configuration \ + import PointConfiguration +from sage.graphs.digraph import DiGraph +from sage.structure.element import Matrix +from oriented_matroids.oriented_matroids_category import OrientedMatroids +import copy + + +def OrientedMatroids(data=None, groundset=None, key=None, **kwds): + r""" + Construct an oriented matroid. + + The implementation of the oriented matroid differentiates which + axiom set that will be used. + + INPUT: + + - ``groundset`` -- (default: ``None``) is the ground set that will be + used for the oriented matroid. + + - ``data`` -- (default: ``None``) the data that will be used to define + the oriented matroids. It can be one of the following: + + + Objects + + + Hyperplane Arrangement + + Point Configuration + + Digraph + + Matrix (not yet implemented) + + + A list or tuple of + + + :class:`SignedSubsetElement` + + :class:`SignedVectorElement` + + A tuple with positive, negative, and zero sets. + + - ``key`` -- (default: ``None``) is the representation of the + oriented matroid. It can be one of the following: + + + ``'covector'`` - uses covector axioms with covectors + + ``'vector'`` - uses vector axioms with signed subsets + + ``'circuit'`` - uses circuit axioms with signed subsets + + ``None`` - try and guess key. + + Further options: + + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + + sage: A = hyperplane_arrangements.braid(3) + sage: M = OrientedMatroids(A); M + Hyperplane arrangement oriented matroid of rank 2 + sage: M.groundset() + (Hyperplane 0*t0 + t1 - t2 + 0, + Hyperplane t0 - t1 + 0*t2 + 0, + Hyperplane t0 + 0*t1 - t2 + 0) + sage: M.elements() + [(0,0,0), + (0,1,1), + (0,-1,-1), + (1,0,1), + (1,1,1), + (1,-1,0), + (1,-1,1), + (1,-1,-1), + (-1,0,-1), + (-1,1,0), + (-1,1,1), + (-1,1,-1), + (-1,-1,-1)] + + sage: D = DiGraph({'v1':{'v2':1,'v3':2,'v4':3},'v2':{'v3':4,'v4':5},'v3':{'v4':6}}) + sage: M = OrientedMatroid(D,key="circuit"); M + Circuit oriented matroid of rank 3 + sage: len(M.circuits()) + 14 + + sage: PC = PointConfiguration([[1,0,0],[0,1,0],[0,0,1],[1/2,1/2,0],[0,1/2,1/2],[1/3,1/3,1/3]]) + sage: M = OrientedMatroid(PC); M + Circuit oriented matroid of rank 3 + sage: M.matroid() + Matroid of rank 3 on 6 elements with 16 bases + + sage: OrientedMatroid([[0]],key='covector') + Covector oriented matroid of rank 0 + sage: OrientedMatroid([[0]],key='circuit') + Traceback (most recent call last): + ... + ValueError: Empty set not allowed + + OUTPUT: + + An oriented matroid whose axioms are determined by the type. + + .. TODO:: + + - Currently chirotopes are not implemented + - We need a way to go from one type to another + + .. SEEALSO:: + + :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` + + REFERENCES: + + For more information see [BLSWZ1999]_ . + + """ + + # Instantiate oriented matroid + OM = None + + # If we have a hyperplane arrangement we need to force the key to be an + # arrangement, + if isinstance(data, HyperplaneArrangementElement): + if key != 'covector' and key is not None: + raise ValueError( + 'Hyperplane arrangements are currently only implemented using covector axioms') + key = 'real_hyperplane_arrangement' + elif isinstance(data, PointConfiguration): + if key != 'circuit' and key is not None: + raise ValueError( + 'Point configurations are currently only implemented using circuit axioms') + key = 'circuit' + # PC circuits are given as (+, 0, -); and only half are given + ci = [(C[0], C[2], C[1]) for C in data.circuits()] + ci += [(C[2], C[0], C[1]) for C in data.circuits()] + data = ci + elif isinstance(data, DiGraph): + if key != 'circuit' and key is not None: + raise ValueError( + 'Digraphs are currently only implemented using circuit axioms') + key = 'circuit' + + # we need to add negative edges in order to do all simple cycles + digraph = copy.copy(data) + edges = copy.copy(list(digraph.edges())) + groundset = [] + if len(edges) != len(set(edges)): + raise ValueError('Edge labels need to be unique') + if None in digraph.edge_labels(): + raise ValueError('Edge labels must be set for all edges') + + # Add minus edges to properly get cycles + for e in edges: + digraph.add_edge(e[1], e[0], "NEG_"+str(e[2])) + groundset.append(str(e[2])) + # Each cycle defines a circuit + data = [] + for c in digraph.all_cycles_iterator(simple=True): + p = set([]) + n = set([]) + for e in range(len(c) - 1): + e = str(digraph.edge_label(c[e], c[e+1])) + if e.startswith('NEG_'): + n.add(e.strip('NEG_')) + else: + p.add(e) + # If an edge exists in both sets, then this is a false cycle. + # This implies we have ee^-1 which is why it's false. + # So we only add the true ones. + if len(p.intersection(n)) == 0: + data.append([p, n]) + elif isinstance(data, Matrix): + if key != 'chirotope' and key is not None: + raise ValueError( + 'Matrices are currently only implemented using chirotope axioms') + key = 'chirotope' + + if key not in OrientedMatroids.keys: + raise ValueError("invalid type key") + + # In the following cases, deep_tupler is used since we are using + # UniqueRepresentation Which doesn't allow us to have non-hashable things. + if key == "covector": + from oriented_matroids.covector_oriented_matroid \ + import CovectorOrientedMatroid + data = deep_tupler(data) + if groundset is not None: + groundset = deep_tupler(groundset) + OM = CovectorOrientedMatroid(data, groundset=groundset) + elif key == "circuit": + from oriented_matroids.circuit_oriented_matroid \ + import CircuitOrientedMatroid + data = deep_tupler(data) + if groundset is not None: + groundset = deep_tupler(groundset) + OM = CircuitOrientedMatroid(data, groundset=groundset) + elif key == "vector": + from oriented_matroids.vector_oriented_matroid \ + import VectorOrientedMatroid + data = deep_tupler(data) + if groundset is not None: + groundset = deep_tupler(groundset) + OM = VectorOrientedMatroid(data, groundset=groundset) + elif key == "real_hyperplane_arrangement": + from oriented_matroids.real_hyperplane_arrangement_oriented_matroid \ + import RealHyperplaneArrangementOrientedMatroid + A = copy.copy(data) + if groundset is None: + groundset = deep_tupler(A.hyperplanes()) + else: + groundset = deep_tupler(groundset) + OM = RealHyperplaneArrangementOrientedMatroid(A, groundset=groundset) + + if OM is None: + raise NotImplementedError( + "Oriented matroid of type {} is not implemented".format(key)) + + if OM.is_valid(): + return OM + + raise ValueError("Oriented matroid is not valid") + + +def deep_tupler(obj): + r""" + changes a (nested) list or set into a (nested) tuple to be hashable + """ + if isinstance(obj, list) or isinstance(obj, set): + return tuple([deep_tupler(i) for i in obj]) + return obj \ No newline at end of file From 138386887c0eee02aaf372a592ef4db23985c5fd Mon Sep 17 00:00:00 2001 From: lizzy Date: Mon, 10 Jul 2023 11:19:04 +0100 Subject: [PATCH 045/101] Removing importing category --- oriented_matroids/constructor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/oriented_matroids/constructor.py b/oriented_matroids/constructor.py index 76aa607..77dd544 100644 --- a/oriented_matroids/constructor.py +++ b/oriented_matroids/constructor.py @@ -40,7 +40,6 @@ import PointConfiguration from sage.graphs.digraph import DiGraph from sage.structure.element import Matrix -from oriented_matroids.oriented_matroids_category import OrientedMatroids import copy From 0b9de9e60a2f6386b3c99b247642315434ba8158 Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 11 Jul 2023 13:52:33 +0100 Subject: [PATCH 046/101] changes to improve Pycodestyle --- oriented_matroids/oriented_matroid.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index dfbec98..d918c89 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -156,7 +156,7 @@ def is_valid(self): to ensure that we actually do have an oriented matroid. """ pass - + def groundset(self): """ Return the ground set of ``self``. @@ -170,7 +170,7 @@ def groundset(self): """ return self._groundset - + def elements(self): """ Return elements. @@ -180,7 +180,7 @@ def elements(self): an oriented matroid defined using covectors. """ return self._elements - + def circuits(self): """ Return all circuits. @@ -188,7 +188,7 @@ def circuits(self): if "_circuits" in dir(self): return self._circuits raise NotImplementedError("Circuits not implemented") - + def cocircuits(self): """ Return all cocircuits. @@ -205,7 +205,7 @@ def vectors(self): return self._vectors raise NotImplementedError("Vectors not implemented") pass - + def covectors(self): """ Return all covectors. @@ -213,7 +213,7 @@ def covectors(self): if "_covectors" in dir(self): return self._covectors raise NotImplementedError("Covectors not implemented") - + def to_circuit(self): """ Return circuit oriented matroid. @@ -222,7 +222,7 @@ def to_circuit(self): return OrientedMatroid(self.circuits(), key='circuit', groundset=self.groundset()) - + def to_vector(self): """ Return vector oriented matroid. @@ -231,7 +231,7 @@ def to_vector(self): return OrientedMatroid(self.vectors(), key='vector', groundset=self.groundset()) - + def to_covector(self): """ Return covector oriented matroid. @@ -240,19 +240,19 @@ def to_covector(self): return OrientedMatroid(self.covectors(), key='covector', groundset=self.groundset()) - + def dual(self): """ Return the dual oriented matroid. """ pass - + def matroid(self): r""" Returns the underlying matroid. """ pass - + def rank(self): r""" Return the rank. @@ -271,7 +271,7 @@ def rank(self): 3 """ return self.matroid().rank() - + def an_element(self): """ Returns an arbitrary element. From 88930c03d49a49e7d8dacf5e6c13942e837a9783 Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 11 Jul 2023 13:58:26 +0100 Subject: [PATCH 047/101] Finishing chages for pycodestyle --- oriented_matroids/oriented_matroid.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index d918c89..f90435d 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -280,7 +280,7 @@ def an_element(self): els = self.elements() i = randint(1, len(els)) return els[i-1] - + def face_poset(self, facade=False): r""" Returns the (big) face poset. @@ -308,7 +308,7 @@ def face_poset(self, facade=False): if Y.is_conformal_with(X) and Y.support().issubset(X.support()) ] return MeetSemilattice((els, rels), cover_relations=False, facade=facade) - + def face_lattice(self, facade=False): r""" Returns the (big) face lattice. @@ -359,7 +359,7 @@ def topes(self): A *tope* is the maximal covector in the face poset. """ return self.face_poset(facade=True).maximal_elements() - + def tope_poset(self, base_tope, facade=False): r""" Returns the tope poset. @@ -380,7 +380,7 @@ def tope_poset(self, base_tope, facade=False): ] return Poset((els, rels), cover_relations=False, facade=facade) - + def is_simplicial(self): r""" Returns if the oriented matroid is simplicial. @@ -395,7 +395,7 @@ def is_simplicial(self): if not t.is_simplicial(): return False return True - + def is_acyclic(self): r""" Return if oriented matroid is acyclic. @@ -408,7 +408,7 @@ def is_acyclic(self): if len(t.negatives()) == 0: return True return False - + def deletion(self, change_set): r""" Returns a covector oriented matroid of a deletion. @@ -445,7 +445,7 @@ def deletion(self, change_set): from oriented_matroids import OrientedMatroid return OrientedMatroid(data, key='covector', groundset=groundset) - + def restriction(self, change_set): r""" Returns a covector oriented matroid of a restriction. @@ -487,7 +487,7 @@ def restriction(self, change_set): from oriented_matroids import OrientedMatroid return OrientedMatroid(data, key='covector', groundset=groundset) - + def loops(self): r""" Returns the loops of an oriented matroid. @@ -504,7 +504,7 @@ def loops(self): if T(j) == 0: loops.append(gs[i]) return loops - + def are_parallel(self, e, f): r""" Returns whether two elements in ground set are parallel. @@ -521,7 +521,7 @@ def are_parallel(self, e, f): if i(e) == 0 and i(f) != 0: return False return True - + def is_simple(self): r""" Returns if the oriented matroid is simple. @@ -536,7 +536,7 @@ def is_simple(self): if self.are_parallel(i[0], i[1]): return False return True - + def _element_constructor_(self, x): r""" Determine if ``x`` may be viewed as belonging to ``self``. From 945c8bf40bbbc0c18db9423c83d4a92dabd36e33 Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 11 Jul 2023 14:01:15 +0100 Subject: [PATCH 048/101] Changes for pycodestyle --- oriented_matroids/circuit_oriented_matroid.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 615b626..b4c9bfd 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -19,8 +19,6 @@ # http://www.gnu.org/licenses/ ############################################################################## - - from oriented_matroids.signed_subset_element import SignedSubsetElement from oriented_matroids.oriented_matroid import OrientedMatroid From 773720bc2bea8ce39f408accfb0ebc5a0b2d79c7 Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 11 Jul 2023 14:04:16 +0100 Subject: [PATCH 049/101] Changing covector for pycodestyle --- oriented_matroids/covector_oriented_matroid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 6b78bde..2dd2297 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -87,7 +87,7 @@ def __classcall__(cls, data, groundset=None): """ Normalize arguments and set class. """ - + return super(CovectorOrientedMatroid, cls) \ .__classcall__(cls, data, groundset=groundset) From c0f35d3105503c1287244c7cf56b89e361700e2c Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 11 Jul 2023 14:08:57 +0100 Subject: [PATCH 050/101] Changing hyperplane for pycodestlye --- .../real_hyperplane_arrangement_oriented_matroid.py | 1 - 1 file changed, 1 deletion(-) diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index b0fc481..fd57f78 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -68,7 +68,6 @@ def __classcall__(cls, data, groundset=None): """ Normalize arguments and set class. """ - return super(RealHyperplaneArrangementOrientedMatroid, cls) \ .__classcall__(cls, data=data, From 9f92393326fe00b5ca69d2ba26f03ec40309a3de Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 11 Jul 2023 14:13:52 +0100 Subject: [PATCH 051/101] Final changes to get a green tick --- oriented_matroids/oriented_matroid.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index f90435d..2684d02 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -163,10 +163,10 @@ def groundset(self): EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid - sage: A = hyperplane_arrangements.braid(2) - sage: M = OrientedMatroid(A); M.groundset() - (Hyperplane t0 - t1 + 0,) + sage: from oriented_matroids import OrientedMatroid + sage: A = hyperplane_arrangements.braid(2) + sage: M = OrientedMatroid(A); M.groundset() + (Hyperplane t0 - t1 + 0,) """ return self._groundset @@ -262,13 +262,13 @@ def rank(self): EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid - sage: A = hyperplane_arrangements.braid(3) - sage: M = OrientedMatroid(A); M.rank() - 2 - sage: A = hyperplane_arrangements.braid(4) - sage: M = OrientedMatroid(A); M.rank() - 3 + sage: from oriented_matroids import OrientedMatroid + sage: A = hyperplane_arrangements.braid(3) + sage: M = OrientedMatroid(A); M.rank() + 2 + sage: A = hyperplane_arrangements.braid(4) + sage: M = OrientedMatroid(A); M.rank() + 3 """ return self.matroid().rank() From d66819c8772be5ec99fc74a64b08ddef30b5aec0 Mon Sep 17 00:00:00 2001 From: lizzyflight <136332529+lizzyflight@users.noreply.github.com> Date: Tue, 11 Jul 2023 14:17:24 +0100 Subject: [PATCH 052/101] Delete oriented_matroids_category.py --- .../oriented_matroids_category.py | 479 ------------------ 1 file changed, 479 deletions(-) delete mode 100644 oriented_matroids/oriented_matroids_category.py diff --git a/oriented_matroids/oriented_matroids_category.py b/oriented_matroids/oriented_matroids_category.py deleted file mode 100644 index 2ceb748..0000000 --- a/oriented_matroids/oriented_matroids_category.py +++ /dev/null @@ -1,479 +0,0 @@ -# -*- coding: utf-8 -*- -r""" -Category of Oriented Matroids -""" -# ***************************************************************************** -# Copyright (C) 2019 Aram Dermenjian -# -# Distributed under the terms of the GNU General Public License (GPL) -# http://www.gnu.org/licenses/ -# ****************************************************************************** - -from sage.misc.abstract_method import abstract_method -from sage.misc.cachefunc import cached_method -from sage.categories.category import Category -from sage.categories.sets_cat import Sets - - -class OrientedMatroids(Category): - r""" - The category of oriented matroids. - - Given a set `E` a signed subset of `E` is a pair `X = (X^+,X^-)` where - `X^+,X^- \subseteq E` and `X^+ \cap X^- = \emptyset`. The support of `X` - is the set `\underline{X} = X^+ \cup X^-`. An *oriented matroid* is a - pair `M = (E,\mathcal{C})` where `E` is a set and `\mathcal{C}` is a - collection of signed subsets of `E` that satisfy certain axioms. An example - of these axioms are the circuit axioms: - - - `\emptyset \not\in \mathcal{C}` - - `\mathcal{C}= -\mathcal{C}` - - for all `X,Y \in \mathcal{C}`, - if `\underline{X} \subseteq \underline{Y}` then `X = Y` or `X = -Y`. - - for all `X,Y \in \mathcal{C}`, `X \neq -Y`, and `e \in X^+ \cap Y^-` - there is a `Z \in \mathcal{C}` such that - `Z^+ \subseteq \left(X^+ \cup Y^+\right) \backslash \left\{e\right\}` - and - `Z^- \subseteq \left(X^- \cup Y^-\right) \backslash \left\{e\right\}`. - - See :wikipedia:`Oriented_matroid` for details. - - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroids - sage: M = OrientedMatroids(); M - Category of oriented matroids - sage: M.super_categories() - [Category of sets] - - .. SEEALSO:: - - :class:`oriented_matroids.oriented_matroid.OrientedMatroid` - - TESTS:: - - sage: TestSuite(M).run() - """ - - """ - List of all possible keys - """ - keys = ['circuit', 'covector', 'vector', 'real_hyperplane_arrangement'] - - @cached_method - def super_categories(self): - """ - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroids - sage: OrientedMatroids().super_categories() - [Category of sets] - """ - return [Sets()] - - class ParentMethods: - - @abstract_method - def is_valid(self): - r""" - Return whether satisfies oriented matroid axioms. - - Given a set of objects, this method tests against - a provided set of axioms for a given representation - to ensure that we actually do have an oriented matroid. - """ - pass - - def groundset(self): - """ - Return the ground set of ``self``. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: A = hyperplane_arrangements.braid(2) - sage: M = OrientedMatroid(A); M.groundset() - (Hyperplane t0 - t1 + 0,) - - """ - return self._groundset - - def elements(self): - """ - Return elements. - - The elements of an oriented matroid are the "defining" elements of - the oriented matroid. For example, covectors are the elements of - an oriented matroid defined using covectors. - """ - return self._elements - - def circuits(self): - """ - Return all circuits. - """ - if "_circuits" in dir(self): - return self._circuits - raise NotImplementedError("Circuits not implemented") - - def cocircuits(self): - """ - Return all cocircuits. - """ - if "_cocircuits" in dir(self): - return self._cocircuits - raise NotImplementedError("Cocircuits not implemented") - - def vectors(self): - """ - Return all vectors. - """ - if "_vectors" in dir(self): - return self._vectors - raise NotImplementedError("Vectors not implemented") - pass - - def covectors(self): - """ - Return all covectors. - """ - if "_covectors" in dir(self): - return self._covectors - raise NotImplementedError("Covectors not implemented") - - def to_circuit(self): - """ - Return circuit oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.circuits(), - key='circuit', - groundset=self.groundset()) - - def to_vector(self): - """ - Return vector oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.vectors(), - key='vector', - groundset=self.groundset()) - - def to_covector(self): - """ - Return covector oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.covectors(), - key='covector', - groundset=self.groundset()) - - def dual(self): - """ - Return the dual oriented matroid. - """ - pass - - @cached_method - def matroid(self): - r""" - Returns the underlying matroid. - """ - pass - - # @cached_method - def rank(self): - r""" - Return the rank. - - The *rank* of an oriented matroid is the rank of its underlying - matroid. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: A = hyperplane_arrangements.braid(3) - sage: M = OrientedMatroid(A); M.rank() - 2 - sage: A = hyperplane_arrangements.braid(4) - sage: M = OrientedMatroid(A); M.rank() - 3 - """ - return self.matroid().rank() - - def an_element(self): - """ - Returns an arbitrary element. - """ - from sage.misc.prandom import randint - els = self.elements() - i = randint(1, len(els)) - return els[i-1] - - def face_poset(self, facade=False): - r""" - Returns the (big) face poset. - - The *(big) face poset* is the poset on covectors such that `X \leq Y` - if and only if `S(X,Y) = \emptyset` and - `\underline{Y} \subseteq \underline{X}`. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], - ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], - ....: [0,0,0]] - sage: M = OrientedMatroid(C, key='covector') - sage: M.face_poset() - Finite meet-semilattice containing 13 elements - """ - from sage.combinat.posets.lattices import MeetSemilattice - els = self.covectors() - rels = [ - (Y, X) - for X in els - for Y in els - if Y.is_conformal_with(X) and Y.support().issubset(X.support()) - ] - return MeetSemilattice((els, rels), cover_relations=False, facade=facade) - - def face_lattice(self, facade=False): - r""" - Returns the (big) face lattice. - - The *(big) face lattice* is the (big) face poset with a top element - added. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], - ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], - ....: [0,0,0]] - sage: M = OrientedMatroid(C, key='covector') - sage: M.face_lattice() - Finite lattice containing 14 elements - """ - from sage.combinat.posets.lattices import LatticePoset - els = self.covectors() - rels = [ - (Y, X) - for X in els - for Y in els - if Y.is_conformal_with(X) and Y.support().issubset(X.support()) - ] - - # Add top element - for i in els: - rels.append((i, 1)) - els.append(1) - return LatticePoset((els, rels), cover_relations=False, facade=facade) - -# P = self.face_poset() -# rels = P.relations() -# els = [1] -# for i in P: -# els.append(i.element) -# rels.append([i.element, 1]) -# -# return LatticePoset((els,rels), -# cover_relations=False, -# facade=facade) - - def topes(self): - r""" - Returns the topes. - - A *tope* is the maximal covector in the face poset. - """ - return self.face_poset(facade=True).maximal_elements() - - def tope_poset(self, base_tope, facade=False): - r""" - Returns the tope poset. - - The tope poset is the poset `(\mathcal{T}, B)` where `\mathcal{T}` - is the set of topes and `B` is a distinguished tope called the - *base tope*. The order is given by inclusion of separation sets - from the base tope: `X \leq Y` if and only if - `S(B, X) \subseteq S(B, Y)`. - """ - from sage.combinat.posets.posets import Poset - els = self.topes() - rels = [ - (X, Y) - for X in els - for Y in els - if base_tope.separation_set(X).issubset(base_tope.separation_set(Y)) - ] - - return Poset((els, rels), cover_relations=False, facade=facade) - - def is_simplicial(self): - r""" - Returns if the oriented matroid is simplicial. - - An oriented matroid is *simplicial* if every tope is simplicial. - - .. SEEALSO:: - - :meth:`~sage.matroids.oriented_matroids.signed_subset_element.SignedSubsetElement.is_simplicial` - """ - for t in self.topes(): - if not t.is_simplicial(): - return False - return True - - def is_acyclic(self): - r""" - Return if oriented matroid is acyclic. - - A covector oriented matroid is *acyclic* if there exists a positive - tope where a *positive tope* is defined as a tope with no - negative part. - """ - for t in self.topes(): - if len(t.negatives()) == 0: - return True - return False - - def deletion(self, change_set): - r""" - Returns a covector oriented matroid of a deletion. - - Let `M = (E, \mathcal{L})` be an oriented matroid over a set `E` - and a set of covectors `\mathcal{L}`. Given `A \subseteq E`, the - *deletion* is the (covector) oriented matroid - `M\backslash A = (E \backslash A, \mathcal{L} \backslash A)` where - - .. MATH:: - - \mathcal{C} \backslash A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C}\right\} - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - - """ - if change_set in self.groundset(): - change_set = set([change_set]) - else: - change_set = set(change_set) - - from oriented_matroids.oriented_matroid import deep_tupler - groundset = set(self.groundset()).difference(change_set) - groundset = deep_tupler(groundset) - data = [] - for c in self.covectors(): - p = tuple(c.positives().difference(change_set)) - n = tuple(c.negatives().difference(change_set)) - z = tuple(c.zeroes().difference(change_set)) - data.append((p, n, z)) - data = deep_tupler(data) - - from oriented_matroids import OrientedMatroid - return OrientedMatroid(data, key='covector', groundset=groundset) - - def restriction(self, change_set): - r""" - Returns a covector oriented matroid of a restriction. - - Given an oriented matroid `M = (E, \mathcal{L})` where `E` is a - set and `\mathcal{L}` is the set of covectors. Given - `A \subseteq E`, the *restriction* is the (covector) oriented - matroid `M / A = (E \backslash A, \mathcal{C} / A)` where - - .. MATH:: - - \mathcal{C} / A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C} \text{ and} A \subseteq X^0 \right\} - - """ - # sage: from oriented_matroids import OrientedMatroid - # sage: A = hyperplane_arrangements.braid(3) - # sage: M = OrientedMatroid(A); M - # Covector Oriented Matroid of rank 3 - # sage: R = M.restriction(M.groundset()[1]); R - # Covector Oriented Matroid of rank 2 - # sage: R.elements() - # [(0,0), (1,1), (-1,-1)] - if change_set in self.groundset(): - change_set = set([change_set]) - else: - change_set = set(change_set) - - from oriented_matroids.oriented_matroid import deep_tupler - groundset = set(self.groundset()).difference(change_set) - groundset = deep_tupler(groundset) - data = [] - for c in self.covectors(): - p = tuple(c.positives().difference(change_set)) - n = tuple(c.negatives().difference(change_set)) - z = tuple(c.zeroes().difference(change_set)) - if change_set.issubset(c.zeroes()): - data.append((p, n, z)) - data = deep_tupler(data) - - from oriented_matroids import OrientedMatroid - return OrientedMatroid(data, key='covector', groundset=groundset) - - def loops(self): - r""" - Returns the loops of an oriented matroid. - - A *loop* is an element `e \in E` such that there is a - tope `T \in \mathcal{T}` with `T(e) = 0`. In particular - if `T(e) = 0` for some `T`, then it is true for all - `T \in \mathcal{T}`. - """ - T = self.topes()[0] - loops = [] - gs = self.groundset() - for i, j in enumerate(T): - if T(j) == 0: - loops.append(gs[i]) - return loops - - def are_parallel(self, e, f): - r""" - Returns whether two elements in ground set are parallel. - - Two elements in the ground set `e, f \in E` are parallel if they - are not loops and for all `X \in \mathcal{C}`, `X(e) = 0` - implies `X(f) = 0`. See Lemma 4.1.10 [BLSWZ1999]_ . - """ - gs = set(self.groundset()).difference(set(self.loops())) - if e not in gs or f not in gs: - raise ValueError( - "Elements must be in groundset and must not be loops") - for i in self.elements(): - if i(e) == 0 and i(f) != 0: - return False - return True - - def is_simple(self): - r""" - Returns if the oriented matroid is simple. - - An oriented matroid is *simple* if there are no loops - and no parallel elements. - """ - from sage.combinat.subset import Subsets - if len(self.loops()) > 0: - return False - for i in Subsets(self.groundset(), 2): - if self.are_parallel(i[0], i[1]): - return False - return True - - def _element_constructor_(self, x): - r""" - Determine if ``x`` may be viewed as belonging to ``self``. - """ - try: - if x in self.elements(): - return x - return False - except ValueError: - return False From b4c5747ebd83873e9c885adf64200652bce4197a Mon Sep 17 00:00:00 2001 From: lizzyflight <136332529+lizzyflight@users.noreply.github.com> Date: Tue, 11 Jul 2023 14:18:10 +0100 Subject: [PATCH 053/101] Delete catalog.py --- oriented_matroids/catalog.py | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 oriented_matroids/catalog.py diff --git a/oriented_matroids/catalog.py b/oriented_matroids/catalog.py deleted file mode 100644 index 524db9d..0000000 --- a/oriented_matroids/catalog.py +++ /dev/null @@ -1,7 +0,0 @@ -r""" -Documentation for the oriented matroids in the catalog - -AUTHORS: - -- Aram Dermenjian (): initial version -""" From 491256465a9baa45dd946dff0cb712c9daa1dde9 Mon Sep 17 00:00:00 2001 From: lizzyflight <136332529+lizzyflight@users.noreply.github.com> Date: Tue, 11 Jul 2023 14:25:37 +0100 Subject: [PATCH 054/101] Delete all.py --- oriented_matroids/all.py | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 oriented_matroids/all.py diff --git a/oriented_matroids/all.py b/oriented_matroids/all.py deleted file mode 100644 index c14aa58..0000000 --- a/oriented_matroids/all.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import absolute_import -from oriented_matroid import OrientedMatroid -from oriented_matroids_category import OrientedMatroids - -# from sage.misc.lazy_import import lazy_import -# lazy_import('sage.matroids.oriented_matroids', -# 'oriented_matroids_catalog', -# 'oriented_matroids') From c26226c80d21afcb6eea8d3abf9ead4bb3787650 Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 11 Jul 2023 14:28:21 +0100 Subject: [PATCH 055/101] Removing catalog and category references --- oriented_matroids/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py index 6202b25..a09c8cb 100644 --- a/oriented_matroids/__init__.py +++ b/oriented_matroids/__init__.py @@ -1,7 +1,6 @@ from __future__ import absolute_import from .oriented_matroid import OrientedMatroid -from .oriented_matroids_category import OrientedMatroids from sage.misc.lazy_import import lazy_import lazy_import('sage.matroids.oriented_matroids', - 'oriented_matroids_catalog', 'oriented_matroids') + 'oriented_matroids') From 63fc2065b0e9aba6d6772d7b055f095da96e067f Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 11 Jul 2023 15:13:11 +0100 Subject: [PATCH 056/101] Changing file name --- oriented_matroids/all.py | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 oriented_matroids/all.py diff --git a/oriented_matroids/all.py b/oriented_matroids/all.py new file mode 100644 index 0000000..b1a468c --- /dev/null +++ b/oriented_matroids/all.py @@ -0,0 +1,6 @@ +from __future__ import absolute_import +from constructor import OrientedMatroid + +from sage.misc.lazy_import import lazy_import +lazy_import('sage.matroids.oriented_matroids', + 'oriented_matroids') From e542480fbe7a19d6192eaf7a4c944ae8c1f12ff3 Mon Sep 17 00:00:00 2001 From: lizzyflight <136332529+lizzyflight@users.noreply.github.com> Date: Tue, 11 Jul 2023 15:17:55 +0100 Subject: [PATCH 057/101] Delete __init__.py --- oriented_matroids/__init__.py | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 oriented_matroids/__init__.py diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py deleted file mode 100644 index b1a468c..0000000 --- a/oriented_matroids/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import absolute_import -from constructor import OrientedMatroid - -from sage.misc.lazy_import import lazy_import -lazy_import('sage.matroids.oriented_matroids', - 'oriented_matroids') From d8d8e7e5c9d2926ec06c1633fb7e5668e3fbffe3 Mon Sep 17 00:00:00 2001 From: lizzyflight <136332529+lizzyflight@users.noreply.github.com> Date: Tue, 11 Jul 2023 15:21:18 +0100 Subject: [PATCH 058/101] Delete oriented_matroids_category.rst --- .../oriented_matroids/oriented_matroids_category.rst | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 docs/source/oriented_matroids/oriented_matroids_category.rst diff --git a/docs/source/oriented_matroids/oriented_matroids_category.rst b/docs/source/oriented_matroids/oriented_matroids_category.rst deleted file mode 100644 index 7fe01be..0000000 --- a/docs/source/oriented_matroids/oriented_matroids_category.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. nodoctest - -Oriented Matroids Category -========================== - -.. automodule:: oriented_matroids.oriented_matroids_category - :members: - :undoc-members: - :show-inheritance: From 36a228d5bdaa2bd4aa2c08a0f7e7a767085635fe Mon Sep 17 00:00:00 2001 From: lizzyflight <136332529+lizzyflight@users.noreply.github.com> Date: Tue, 11 Jul 2023 15:25:18 +0100 Subject: [PATCH 059/101] Delete oriented_matroids_catalog.py --- oriented_matroids/oriented_matroids_catalog.py | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 oriented_matroids/oriented_matroids_catalog.py diff --git a/oriented_matroids/oriented_matroids_catalog.py b/oriented_matroids/oriented_matroids_catalog.py deleted file mode 100644 index 5b6fb4f..0000000 --- a/oriented_matroids/oriented_matroids_catalog.py +++ /dev/null @@ -1,11 +0,0 @@ -r""" -Catalog of oriented matroids - -A module containing constructors for several common oriented matroids - -""" - -# Do not add code to this file, only imports. - -# user-accessible: -# from sage.matroids.catalog import ... From 4af7f0d90df7d7a0f53048283f542aa61c65c471 Mon Sep 17 00:00:00 2001 From: lizzyflight <136332529+lizzyflight@users.noreply.github.com> Date: Tue, 11 Jul 2023 15:28:01 +0100 Subject: [PATCH 060/101] Create constructor.rst --- docs/source/oriented_matroids/constructor.rst | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 docs/source/oriented_matroids/constructor.rst diff --git a/docs/source/oriented_matroids/constructor.rst b/docs/source/oriented_matroids/constructor.rst new file mode 100644 index 0000000..3bcf0ac --- /dev/null +++ b/docs/source/oriented_matroids/constructor.rst @@ -0,0 +1,9 @@ +.. nodoctest + +Constructor +========================= + +.. automodule:: oriented_matroids.constructor + :members: + :undoc-members: + :show-inheritance: From 7f04eee1529cbfa2e51e98ad73026155ecfc075b Mon Sep 17 00:00:00 2001 From: lizzyflight <136332529+lizzyflight@users.noreply.github.com> Date: Tue, 11 Jul 2023 15:30:25 +0100 Subject: [PATCH 061/101] Rename hyperplane_arrangement_oriented_matroid.rst to real_hyperplane_arrangement_oriented_matroid.rst --- ...troid.rst => real_hyperplane_arrangement_oriented_matroid.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/source/oriented_matroids/{hyperplane_arrangement_oriented_matroid.rst => real_hyperplane_arrangement_oriented_matroid.rst} (100%) diff --git a/docs/source/oriented_matroids/hyperplane_arrangement_oriented_matroid.rst b/docs/source/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.rst similarity index 100% rename from docs/source/oriented_matroids/hyperplane_arrangement_oriented_matroid.rst rename to docs/source/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.rst From d5e009b990c18175dedb32b62866b8c085428e5c Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 11 Jul 2023 15:33:02 +0100 Subject: [PATCH 062/101] Changing OrientedMatroids to OrientedMatroid --- oriented_matroids/constructor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/constructor.py b/oriented_matroids/constructor.py index 77dd544..15b40a6 100644 --- a/oriented_matroids/constructor.py +++ b/oriented_matroids/constructor.py @@ -43,7 +43,7 @@ import copy -def OrientedMatroids(data=None, groundset=None, key=None, **kwds): +def OrientedMatroid(data=None, groundset=None, key=None, **kwds): r""" Construct an oriented matroid. From 333bea8590903f40214fcbcfc234e9673f1dd84a Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 11 Jul 2023 15:39:07 +0100 Subject: [PATCH 063/101] Changing class name and removing category --- oriented_matroids/oriented_matroid.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 2684d02..221f052 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -40,12 +40,11 @@ import PointConfiguration from sage.graphs.digraph import DiGraph from sage.structure.element import Matrix -from oriented_matroids.oriented_matroids_category import OrientedMatroids import copy from sage.structure.sage_object import SageObject -class OrientedMatroid(SageObject): +class AbstractOrientedMatroid(SageObject): r""" Construct an oriented matroid. From fd55d9e15e0359ea72ac1b1f7f88e3b6fee1e30a Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Wed, 12 Jul 2023 14:07:53 +0100 Subject: [PATCH 064/101] Test for Lizzy --- oriented_matroids/fake_file.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 oriented_matroids/fake_file.py diff --git a/oriented_matroids/fake_file.py b/oriented_matroids/fake_file.py new file mode 100644 index 0000000..e69de29 From 035d9543d0f1c8cf5b7da4b1f83c14fa17b90766 Mon Sep 17 00:00:00 2001 From: lizzyflight <136332529+lizzyflight@users.noreply.github.com> Date: Wed, 12 Jul 2023 14:48:32 +0100 Subject: [PATCH 065/101] Update fake_file.py --- oriented_matroids/fake_file.py | 1 + 1 file changed, 1 insertion(+) diff --git a/oriented_matroids/fake_file.py b/oriented_matroids/fake_file.py index e69de29..5fd06e9 100644 --- a/oriented_matroids/fake_file.py +++ b/oriented_matroids/fake_file.py @@ -0,0 +1 @@ +help From 269b35a93a1e397f85ff4fd1255a6a1d2e4b4fa3 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 12 Jul 2023 14:58:08 +0100 Subject: [PATCH 066/101] Removing fake_file --- .../{oriented_matroid.py => abstract_oriented_matroid.py} | 0 oriented_matroids/fake_file.py | 1 - 2 files changed, 1 deletion(-) rename oriented_matroids/{oriented_matroid.py => abstract_oriented_matroid.py} (100%) delete mode 100644 oriented_matroids/fake_file.py diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py similarity index 100% rename from oriented_matroids/oriented_matroid.py rename to oriented_matroids/abstract_oriented_matroid.py diff --git a/oriented_matroids/fake_file.py b/oriented_matroids/fake_file.py deleted file mode 100644 index 5fd06e9..0000000 --- a/oriented_matroids/fake_file.py +++ /dev/null @@ -1 +0,0 @@ -help From 9e3ebcfc4405fdcdfb5bb521eeef3392e1834985 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 12 Jul 2023 15:00:24 +0100 Subject: [PATCH 067/101] Changing to abstract --- oriented_matroids/circuit_oriented_matroid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index b4c9bfd..ffbfb37 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -20,10 +20,10 @@ ############################################################################## from oriented_matroids.signed_subset_element import SignedSubsetElement -from oriented_matroids.oriented_matroid import OrientedMatroid +from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid -class CircuitOrientedMatroid(OrientedMatroid): +class CircuitOrientedMatroid(AbstractOrientedMatroid): r""" An oriented matroid implemented using circuit axioms. From 28b9e044384baf889ad9c5b8d0bd503a38faa3dd Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 12 Jul 2023 15:03:27 +0100 Subject: [PATCH 068/101] Adding Abstract --- oriented_matroids/covector_oriented_matroid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 2dd2297..38fd19f 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -22,12 +22,12 @@ from sage.structure.parent import Parent from oriented_matroids.signed_vector_element import SignedVectorElement -from oriented_matroids.oriented_matroid import OrientedMatroid +from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid import copy -class CovectorOrientedMatroid(OrientedMatroid): +class CovectorOrientedMatroid(AbstractOrientedMatroid): r""" An oriented matroid implemented using covector axioms. From 49500687a1c0dfab74dcf539c09e00ea1ef5ffea Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 12 Jul 2023 15:04:56 +0100 Subject: [PATCH 069/101] Adding Abstract --- oriented_matroids/vector_oriented_matroid.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index 41eb71c..7a2791b 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -19,12 +19,12 @@ # http://www.gnu.org/licenses/ ############################################################################## -from oriented_matroids.oriented_matriod import OrientedMatroid +from oriented_matroids.abstract_oriented_matriod import AbstractOrientedMatroid from sage.structure.parent import Parent from oriented_matroids.signed_vector_element import SignedVectorElement -class VectorOrientedMatroid(OrientedMatroid): +class VectorOrientedMatroid(AbstractOrientedMatroid): r""" An oriented matroid implemented using vector axioms. From f10b83dd71e94b4e8dc89c8bfa81898a34aaf8eb Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 12 Jul 2023 15:21:05 +0100 Subject: [PATCH 070/101] Removing the s off OrientedMatroids --- oriented_matroids/constructor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/constructor.py b/oriented_matroids/constructor.py index a7114bd..ce9cbfe 100644 --- a/oriented_matroids/constructor.py +++ b/oriented_matroids/constructor.py @@ -206,7 +206,7 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): 'Matrices are currently only implemented using chirotope axioms') key = 'chirotope' - if key not in OrientedMatroids.keys: + if key not in OrientedMatroid.keys: raise ValueError("invalid type key") # In the following cases, deep_tupler is used since we are using From 62f4bcff33b93c8aaab660f50346cc1cd8fa8bf8 Mon Sep 17 00:00:00 2001 From: lizzy Date: Thu, 13 Jul 2023 12:09:46 +0100 Subject: [PATCH 071/101] Trying to correct the 'key' issue --- oriented_matroids/constructor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/oriented_matroids/constructor.py b/oriented_matroids/constructor.py index ce9cbfe..d9d2028 100644 --- a/oriented_matroids/constructor.py +++ b/oriented_matroids/constructor.py @@ -40,6 +40,7 @@ import PointConfiguration from sage.graphs.digraph import DiGraph from sage.structure.element import Matrix +from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid import copy @@ -206,7 +207,7 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): 'Matrices are currently only implemented using chirotope axioms') key = 'chirotope' - if key not in OrientedMatroid.keys: + if key not in AbstractOrientedMatroid.keys: raise ValueError("invalid type key") # In the following cases, deep_tupler is used since we are using From b599add7ebec66fc5743ae3030b9cca9f302a17e Mon Sep 17 00:00:00 2001 From: lizzy Date: Thu, 13 Jul 2023 12:17:39 +0100 Subject: [PATCH 072/101] Getting rid of previous change --- oriented_matroids/constructor.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/oriented_matroids/constructor.py b/oriented_matroids/constructor.py index d9d2028..ce9cbfe 100644 --- a/oriented_matroids/constructor.py +++ b/oriented_matroids/constructor.py @@ -40,7 +40,6 @@ import PointConfiguration from sage.graphs.digraph import DiGraph from sage.structure.element import Matrix -from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid import copy @@ -207,7 +206,7 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): 'Matrices are currently only implemented using chirotope axioms') key = 'chirotope' - if key not in AbstractOrientedMatroid.keys: + if key not in OrientedMatroid.keys: raise ValueError("invalid type key") # In the following cases, deep_tupler is used since we are using From a1d0b327ca13b81a443241a6e90226565e73a240 Mon Sep 17 00:00:00 2001 From: lizzy Date: Thu, 13 Jul 2023 14:59:33 +0100 Subject: [PATCH 073/101] # current error with keys --- oriented_matroids/constructor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/constructor.py b/oriented_matroids/constructor.py index ce9cbfe..23c8fd7 100644 --- a/oriented_matroids/constructor.py +++ b/oriented_matroids/constructor.py @@ -206,8 +206,8 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): 'Matrices are currently only implemented using chirotope axioms') key = 'chirotope' - if key not in OrientedMatroid.keys: - raise ValueError("invalid type key") + #if key not in OrientedMatroid.keys: + #raise ValueError("invalid type key") # In the following cases, deep_tupler is used since we are using # UniqueRepresentation Which doesn't allow us to have non-hashable things. From 21063b6ce28625fc9be15eb73cc42b9af6f41313 Mon Sep 17 00:00:00 2001 From: lizzy Date: Thu, 13 Jul 2023 15:02:20 +0100 Subject: [PATCH 074/101] Removing parent refernce --- .../real_hyperplane_arrangement_oriented_matroid.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index fd57f78..123c331 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -39,7 +39,7 @@ class RealHyperplaneArrangementOrientedMatroid(CovectorOrientedMatroid): EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.constructor import OrientedMatroid sage: A = hyperplane_arrangements.braid(3) sage: M = OrientedMatroid(A); M Hyperplane arrangement oriented matroid of rank 2 @@ -77,7 +77,6 @@ def __init__(self, data, groundset=None): """ Initialize ``self`` """ - Parent.__init__(self) self._arrangement = data From d271389a078e0b61990997f208ea4542addc2955 Mon Sep 17 00:00:00 2001 From: lizzy Date: Thu, 13 Jul 2023 15:09:18 +0100 Subject: [PATCH 075/101] Removing Parent reference --- oriented_matroids/covector_oriented_matroid.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 38fd19f..e8ceced 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -95,8 +95,6 @@ def __init__(self, data, groundset=None): """ Initialize ``self`` """ - Parent.__init__(self) - # Set up our covectors covectors = [] for d in data: From 9aa4e9bbd609ea3d536b1951d8530f80ea2365a6 Mon Sep 17 00:00:00 2001 From: lizzy Date: Fri, 14 Jul 2023 11:53:44 +0100 Subject: [PATCH 076/101] Fixing bugs for structure update --- oriented_matroids/abstract_oriented_matroid.py | 11 +++++------ oriented_matroids/covector_oriented_matroid.py | 2 -- .../real_hyperplane_arrangement_oriented_matroid.py | 3 +-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py index 221f052..d7ca29b 100644 --- a/oriented_matroids/abstract_oriented_matroid.py +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -34,12 +34,6 @@ # http://www.gnu.org/licenses/ # ***************************************************************************** -from sage.geometry.hyperplane_arrangement.arrangement \ - import HyperplaneArrangementElement -from sage.geometry.triangulation.point_configuration \ - import PointConfiguration -from sage.graphs.digraph import DiGraph -from sage.structure.element import Matrix import copy from sage.structure.sage_object import SageObject @@ -146,6 +140,11 @@ class AbstractOrientedMatroid(SageObject): For more information see [BLSWZ1999]_ . """ + """ + List of all possible keys + """ + keys = ['circuit', 'covector', 'vector', 'real_hyperplane_arrangement'] + def is_valid(self): r""" Return whether satisfies oriented matroid axioms. diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 38fd19f..37e58ce 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -20,7 +20,6 @@ ############################################################################## -from sage.structure.parent import Parent from oriented_matroids.signed_vector_element import SignedVectorElement from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid @@ -95,7 +94,6 @@ def __init__(self, data, groundset=None): """ Initialize ``self`` """ - Parent.__init__(self) # Set up our covectors covectors = [] diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index fd57f78..6c22280 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -19,7 +19,7 @@ # http://www.gnu.org/licenses/ ############################################################################## -from sage.structure.parent import Parent + from oriented_matroids.covector_oriented_matroid import CovectorOrientedMatroid @@ -77,7 +77,6 @@ def __init__(self, data, groundset=None): """ Initialize ``self`` """ - Parent.__init__(self) self._arrangement = data From f4d2c5c804a24fae578b19f4cad50914bbab9914 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Mon, 17 Jul 2023 12:19:02 +0100 Subject: [PATCH 077/101] Fix init file, by removing --- oriented_matroids/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 oriented_matroids/__init__.py diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py new file mode 100644 index 0000000..1bdd1cd --- /dev/null +++ b/oriented_matroids/__init__.py @@ -0,0 +1,7 @@ +from __future__ import absolute_import +from .oriented_matroid import OrientedMatroid +from .oriented_matroids_category import OrientedMatroids + +# from sage.misc.lazy_import import lazy_import +#lazy_import('sage.matroids.oriented_matroids', +# 'oriented_matroids_catalog', 'oriented_matroids') From 3f56622e03d13b90def8b4c45287800d370db4f9 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Mon, 17 Jul 2023 12:30:29 +0100 Subject: [PATCH 078/101] Revert "Fix init file, by removing" This reverts commit f4d2c5c804a24fae578b19f4cad50914bbab9914. --- oriented_matroids/__init__.py | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 oriented_matroids/__init__.py diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py deleted file mode 100644 index 1bdd1cd..0000000 --- a/oriented_matroids/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import absolute_import -from .oriented_matroid import OrientedMatroid -from .oriented_matroids_category import OrientedMatroids - -# from sage.misc.lazy_import import lazy_import -#lazy_import('sage.matroids.oriented_matroids', -# 'oriented_matroids_catalog', 'oriented_matroids') From 6a9cb254de2fcd29e5e646b4bcd6a2ebcc2dbe4a Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Mon, 17 Jul 2023 12:50:21 +0100 Subject: [PATCH 079/101] On branch develop Your branch is up-to-date with 'origin/develop'. --- ...yperplane_arrangement_oriented_matroid.rst | 9 + .../oriented_matroids_category.rst | 9 + oriented_matroids/__init__.py | 7 + oriented_matroids/all.py | 10 +- oriented_matroids/catalog.py | 7 + oriented_matroids/circuit_oriented_matroid.py | 13 +- .../covector_oriented_matroid.py | 17 +- oriented_matroids/oriented_matroid.py | 262 ++++++++++ .../oriented_matroids_catalog.py | 11 + .../oriented_matroids_category.py | 479 ++++++++++++++++++ ...hyperplane_arrangement_oriented_matroid.py | 13 +- oriented_matroids/vector_oriented_matroid.py | 12 +- 12 files changed, 823 insertions(+), 26 deletions(-) create mode 100644 docs/source/oriented_matroids/hyperplane_arrangement_oriented_matroid.rst create mode 100644 docs/source/oriented_matroids/oriented_matroids_category.rst create mode 100644 oriented_matroids/__init__.py create mode 100644 oriented_matroids/catalog.py create mode 100644 oriented_matroids/oriented_matroid.py create mode 100644 oriented_matroids/oriented_matroids_catalog.py create mode 100644 oriented_matroids/oriented_matroids_category.py diff --git a/docs/source/oriented_matroids/hyperplane_arrangement_oriented_matroid.rst b/docs/source/oriented_matroids/hyperplane_arrangement_oriented_matroid.rst new file mode 100644 index 0000000..e75557a --- /dev/null +++ b/docs/source/oriented_matroids/hyperplane_arrangement_oriented_matroid.rst @@ -0,0 +1,9 @@ +.. nodoctest + +Hyperplane Arrangement Oriented Matroids +======================================== + +.. automodule:: oriented_matroids.hyperplane_arrangement_oriented_matroid + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/oriented_matroids/oriented_matroids_category.rst b/docs/source/oriented_matroids/oriented_matroids_category.rst new file mode 100644 index 0000000..7fe01be --- /dev/null +++ b/docs/source/oriented_matroids/oriented_matroids_category.rst @@ -0,0 +1,9 @@ +.. nodoctest + +Oriented Matroids Category +========================== + +.. automodule:: oriented_matroids.oriented_matroids_category + :members: + :undoc-members: + :show-inheritance: diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py new file mode 100644 index 0000000..7ad0a4b --- /dev/null +++ b/oriented_matroids/__init__.py @@ -0,0 +1,7 @@ +from __future__ import absolute_import +from .oriented_matroid import OrientedMatroid +from .oriented_matroids_category import OrientedMatroids + +from sage.misc.lazy_import import lazy_import +#lazy_import('sage.matroids.oriented_matroids', +# 'oriented_matroids_catalog', 'oriented_matroids') diff --git a/oriented_matroids/all.py b/oriented_matroids/all.py index b1a468c..c14aa58 100644 --- a/oriented_matroids/all.py +++ b/oriented_matroids/all.py @@ -1,6 +1,8 @@ from __future__ import absolute_import -from constructor import OrientedMatroid +from oriented_matroid import OrientedMatroid +from oriented_matroids_category import OrientedMatroids -from sage.misc.lazy_import import lazy_import -lazy_import('sage.matroids.oriented_matroids', - 'oriented_matroids') +# from sage.misc.lazy_import import lazy_import +# lazy_import('sage.matroids.oriented_matroids', +# 'oriented_matroids_catalog', +# 'oriented_matroids') diff --git a/oriented_matroids/catalog.py b/oriented_matroids/catalog.py new file mode 100644 index 0000000..524db9d --- /dev/null +++ b/oriented_matroids/catalog.py @@ -0,0 +1,7 @@ +r""" +Documentation for the oriented matroids in the catalog + +AUTHORS: + +- Aram Dermenjian (): initial version +""" diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index ffbfb37..eb562dd 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -19,11 +19,13 @@ # http://www.gnu.org/licenses/ ############################################################################## +from sage.structure.unique_representation import UniqueRepresentation +from sage.structure.parent import Parent +from oriented_matroids.oriented_matroids_category import OrientedMatroids from oriented_matroids.signed_subset_element import SignedSubsetElement -from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid -class CircuitOrientedMatroid(AbstractOrientedMatroid): +class CircuitOrientedMatroid(UniqueRepresentation, Parent): r""" An oriented matroid implemented using circuit axioms. @@ -75,15 +77,18 @@ def __classcall__(cls, data, groundset=None): Normalize arguments and set class. """ + category = OrientedMatroids() return super(CircuitOrientedMatroid, cls) \ .__classcall__(cls, data=data, - groundset=groundset) + groundset=groundset, + category=category) - def __init__(self, data, groundset=None): + def __init__(self, data, groundset=None, category=None): """ Initialize ``self``. """ + Parent.__init__(self, category=category) # Set up our circuits circuits = [] diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 38fd19f..7a08dda 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -19,15 +19,15 @@ # http://www.gnu.org/licenses/ ############################################################################## - +from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent +from oriented_matroids.oriented_matroids_category import OrientedMatroids from oriented_matroids.signed_vector_element import SignedVectorElement -from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid import copy -class CovectorOrientedMatroid(AbstractOrientedMatroid): +class CovectorOrientedMatroid(UniqueRepresentation, Parent): r""" An oriented matroid implemented using covector axioms. @@ -83,19 +83,20 @@ class CovectorOrientedMatroid(AbstractOrientedMatroid): Element = SignedVectorElement @staticmethod - def __classcall__(cls, data, groundset=None): + def __classcall__(cls, data, groundset=None, category=None): """ Normalize arguments and set class. """ - + if category is None: + category = OrientedMatroids() return super(CovectorOrientedMatroid, cls) \ - .__classcall__(cls, data, groundset=groundset) + .__classcall__(cls, data, groundset=groundset, category=category) - def __init__(self, data, groundset=None): + def __init__(self, data, groundset=None, category=None): """ Initialize ``self`` """ - Parent.__init__(self) + Parent.__init__(self, category=category) # Set up our covectors covectors = [] diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py new file mode 100644 index 0000000..0321e64 --- /dev/null +++ b/oriented_matroids/oriented_matroid.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 -*- +r""" +Oriented matroids construction + +Theory +====== + +Oriented matroids are ... + +Built-in oriented matroids +========================== + +... + +Constructing oriented matroids +============================== + +To define your own oriented matroid,... + + +AUTHORS: + +- Aram Dermenjian (2019-07-12): initial version + +""" + +# ***************************************************************************** +# Copyright (C) 2019 Aram Dermenjian +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +# ***************************************************************************** + +from sage.geometry.hyperplane_arrangement.arrangement \ + import HyperplaneArrangementElement +from sage.geometry.triangulation.point_configuration \ + import PointConfiguration +from sage.graphs.digraph import DiGraph +from sage.structure.element import Matrix +from oriented_matroids.oriented_matroids_category import OrientedMatroids +import copy + + +def OrientedMatroid(data=None, groundset=None, key=None, **kwds): + r""" + Construct an oriented matroid. + + The implementation of the oriented matroid differentiates which + axiom set that will be used. + + INPUT: + + - ``groundset`` -- (default: ``None``) is the ground set that will be + used for the oriented matroid. + + - ``data`` -- (default: ``None``) the data that will be used to define + the oriented matroids. It can be one of the following: + + + Objects + + + Hyperplane Arrangement + + Point Configuration + + Digraph + + Matrix (not yet implemented) + + + A list or tuple of + + + :class:`SignedSubsetElement` + + :class:`SignedVectorElement` + + A tuple with positive, negative, and zero sets. + + - ``key`` -- (default: ``None``) is the representation of the + oriented matroid. It can be one of the following: + + + ``'covector'`` - uses covector axioms with covectors + + ``'vector'`` - uses vector axioms with signed subsets + + ``'circuit'`` - uses circuit axioms with signed subsets + + ``None`` - try and guess key. + + Further options: + + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + + sage: A = hyperplane_arrangements.braid(3) + sage: M = OrientedMatroid(A); M + Hyperplane arrangement oriented matroid of rank 2 + sage: M.groundset() + (Hyperplane 0*t0 + t1 - t2 + 0, + Hyperplane t0 - t1 + 0*t2 + 0, + Hyperplane t0 + 0*t1 - t2 + 0) + sage: M.elements() + [(0,0,0), + (0,1,1), + (0,-1,-1), + (1,0,1), + (1,1,1), + (1,-1,0), + (1,-1,1), + (1,-1,-1), + (-1,0,-1), + (-1,1,0), + (-1,1,1), + (-1,1,-1), + (-1,-1,-1)] + + sage: D = DiGraph({'v1':{'v2':1,'v3':2,'v4':3},'v2':{'v3':4,'v4':5},'v3':{'v4':6}}) + sage: M = OrientedMatroid(D,key="circuit"); M + Circuit oriented matroid of rank 3 + sage: len(M.circuits()) + 14 + + sage: PC = PointConfiguration([[1,0,0],[0,1,0],[0,0,1],[1/2,1/2,0],[0,1/2,1/2],[1/3,1/3,1/3]]) + sage: M = OrientedMatroid(PC); M + Circuit oriented matroid of rank 3 + sage: M.matroid() + Matroid of rank 3 on 6 elements with 16 bases + + sage: OrientedMatroid([[0]],key='covector') + Covector oriented matroid of rank 0 + sage: OrientedMatroid([[0]],key='circuit') + Traceback (most recent call last): + ... + ValueError: Empty set not allowed + + OUTPUT: + + An oriented matroid whose axioms are determined by the type. + + .. TODO:: + + - Currently chirotopes are not implemented + - We need a way to go from one type to another + + .. SEEALSO:: + + :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` + + REFERENCES: + + For more information see [BLSWZ1999]_ . + + """ + + # Instantiate oriented matroid + OM = None + + # If we have a hyperplane arrangement we need to force the key to be an + # arrangement, + if isinstance(data, HyperplaneArrangementElement): + if key != 'covector' and key is not None: + raise ValueError( + 'Hyperplane arrangements are currently only implemented using covector axioms') + key = 'real_hyperplane_arrangement' + elif isinstance(data, PointConfiguration): + if key != 'circuit' and key is not None: + raise ValueError( + 'Point configurations are currently only implemented using circuit axioms') + key = 'circuit' + # PC circuits are given as (+, 0, -); and only half are given + ci = [(C[0], C[2], C[1]) for C in data.circuits()] + ci += [(C[2], C[0], C[1]) for C in data.circuits()] + data = ci + elif isinstance(data, DiGraph): + if key != 'circuit' and key is not None: + raise ValueError( + 'Digraphs are currently only implemented using circuit axioms') + key = 'circuit' + + # we need to add negative edges in order to do all simple cycles + digraph = copy.copy(data) + edges = copy.copy(list(digraph.edges())) + groundset = [] + if len(edges) != len(set(edges)): + raise ValueError('Edge labels need to be unique') + if None in digraph.edge_labels(): + raise ValueError('Edge labels must be set for all edges') + + # Add minus edges to properly get cycles + for e in edges: + digraph.add_edge(e[1], e[0], "NEG_"+str(e[2])) + groundset.append(str(e[2])) + # Each cycle defines a circuit + data = [] + for c in digraph.all_cycles_iterator(simple=True): + p = set([]) + n = set([]) + for e in range(len(c) - 1): + e = str(digraph.edge_label(c[e], c[e+1])) + if e.startswith('NEG_'): + n.add(e.strip('NEG_')) + else: + p.add(e) + # If an edge exists in both sets, then this is a false cycle. + # This implies we have ee^-1 which is why it's false. + # So we only add the true ones. + if len(p.intersection(n)) == 0: + data.append([p, n]) + elif isinstance(data, Matrix): + if key != 'chirotope' and key is not None: + raise ValueError( + 'Matrices are currently only implemented using chirotope axioms') + key = 'chirotope' + + if key not in OrientedMatroids.keys: + raise ValueError("invalid type key") + + # In the following cases, deep_tupler is used since we are using + # UniqueRepresentation Which doesn't allow us to have non-hashable things. + if key == "covector": + from oriented_matroids.covector_oriented_matroid \ + import CovectorOrientedMatroid + data = deep_tupler(data) + if groundset is not None: + groundset = deep_tupler(groundset) + OM = CovectorOrientedMatroid(data, groundset=groundset) + elif key == "circuit": + from oriented_matroids.circuit_oriented_matroid \ + import CircuitOrientedMatroid + data = deep_tupler(data) + if groundset is not None: + groundset = deep_tupler(groundset) + OM = CircuitOrientedMatroid(data, groundset=groundset) + elif key == "vector": + from oriented_matroids.vector_oriented_matroid \ + import VectorOrientedMatroid + data = deep_tupler(data) + if groundset is not None: + groundset = deep_tupler(groundset) + OM = VectorOrientedMatroid(data, groundset=groundset) + elif key == "real_hyperplane_arrangement": + from oriented_matroids.real_hyperplane_arrangement_oriented_matroid \ + import RealHyperplaneArrangementOrientedMatroid + A = copy.copy(data) + if groundset is None: + groundset = deep_tupler(A.hyperplanes()) + else: + groundset = deep_tupler(groundset) + OM = RealHyperplaneArrangementOrientedMatroid(A, groundset=groundset) + + if OM is None: + raise NotImplementedError( + "Oriented matroid of type {} is not implemented".format(key)) + + if OM.is_valid(): + return OM + + raise ValueError("Oriented matroid is not valid") + + +def deep_tupler(obj): + r""" + changes a (nested) list or set into a (nested) tuple to be hashable + """ + if isinstance(obj, list) or isinstance(obj, set): + return tuple([deep_tupler(i) for i in obj]) + return obj diff --git a/oriented_matroids/oriented_matroids_catalog.py b/oriented_matroids/oriented_matroids_catalog.py new file mode 100644 index 0000000..5b6fb4f --- /dev/null +++ b/oriented_matroids/oriented_matroids_catalog.py @@ -0,0 +1,11 @@ +r""" +Catalog of oriented matroids + +A module containing constructors for several common oriented matroids + +""" + +# Do not add code to this file, only imports. + +# user-accessible: +# from sage.matroids.catalog import ... diff --git a/oriented_matroids/oriented_matroids_category.py b/oriented_matroids/oriented_matroids_category.py new file mode 100644 index 0000000..2ceb748 --- /dev/null +++ b/oriented_matroids/oriented_matroids_category.py @@ -0,0 +1,479 @@ +# -*- coding: utf-8 -*- +r""" +Category of Oriented Matroids +""" +# ***************************************************************************** +# Copyright (C) 2019 Aram Dermenjian +# +# Distributed under the terms of the GNU General Public License (GPL) +# http://www.gnu.org/licenses/ +# ****************************************************************************** + +from sage.misc.abstract_method import abstract_method +from sage.misc.cachefunc import cached_method +from sage.categories.category import Category +from sage.categories.sets_cat import Sets + + +class OrientedMatroids(Category): + r""" + The category of oriented matroids. + + Given a set `E` a signed subset of `E` is a pair `X = (X^+,X^-)` where + `X^+,X^- \subseteq E` and `X^+ \cap X^- = \emptyset`. The support of `X` + is the set `\underline{X} = X^+ \cup X^-`. An *oriented matroid* is a + pair `M = (E,\mathcal{C})` where `E` is a set and `\mathcal{C}` is a + collection of signed subsets of `E` that satisfy certain axioms. An example + of these axioms are the circuit axioms: + + - `\emptyset \not\in \mathcal{C}` + - `\mathcal{C}= -\mathcal{C}` + - for all `X,Y \in \mathcal{C}`, + if `\underline{X} \subseteq \underline{Y}` then `X = Y` or `X = -Y`. + - for all `X,Y \in \mathcal{C}`, `X \neq -Y`, and `e \in X^+ \cap Y^-` + there is a `Z \in \mathcal{C}` such that + `Z^+ \subseteq \left(X^+ \cup Y^+\right) \backslash \left\{e\right\}` + and + `Z^- \subseteq \left(X^- \cup Y^-\right) \backslash \left\{e\right\}`. + + See :wikipedia:`Oriented_matroid` for details. + + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroids + sage: M = OrientedMatroids(); M + Category of oriented matroids + sage: M.super_categories() + [Category of sets] + + .. SEEALSO:: + + :class:`oriented_matroids.oriented_matroid.OrientedMatroid` + + TESTS:: + + sage: TestSuite(M).run() + """ + + """ + List of all possible keys + """ + keys = ['circuit', 'covector', 'vector', 'real_hyperplane_arrangement'] + + @cached_method + def super_categories(self): + """ + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroids + sage: OrientedMatroids().super_categories() + [Category of sets] + """ + return [Sets()] + + class ParentMethods: + + @abstract_method + def is_valid(self): + r""" + Return whether satisfies oriented matroid axioms. + + Given a set of objects, this method tests against + a provided set of axioms for a given representation + to ensure that we actually do have an oriented matroid. + """ + pass + + def groundset(self): + """ + Return the ground set of ``self``. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: A = hyperplane_arrangements.braid(2) + sage: M = OrientedMatroid(A); M.groundset() + (Hyperplane t0 - t1 + 0,) + + """ + return self._groundset + + def elements(self): + """ + Return elements. + + The elements of an oriented matroid are the "defining" elements of + the oriented matroid. For example, covectors are the elements of + an oriented matroid defined using covectors. + """ + return self._elements + + def circuits(self): + """ + Return all circuits. + """ + if "_circuits" in dir(self): + return self._circuits + raise NotImplementedError("Circuits not implemented") + + def cocircuits(self): + """ + Return all cocircuits. + """ + if "_cocircuits" in dir(self): + return self._cocircuits + raise NotImplementedError("Cocircuits not implemented") + + def vectors(self): + """ + Return all vectors. + """ + if "_vectors" in dir(self): + return self._vectors + raise NotImplementedError("Vectors not implemented") + pass + + def covectors(self): + """ + Return all covectors. + """ + if "_covectors" in dir(self): + return self._covectors + raise NotImplementedError("Covectors not implemented") + + def to_circuit(self): + """ + Return circuit oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.circuits(), + key='circuit', + groundset=self.groundset()) + + def to_vector(self): + """ + Return vector oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.vectors(), + key='vector', + groundset=self.groundset()) + + def to_covector(self): + """ + Return covector oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.covectors(), + key='covector', + groundset=self.groundset()) + + def dual(self): + """ + Return the dual oriented matroid. + """ + pass + + @cached_method + def matroid(self): + r""" + Returns the underlying matroid. + """ + pass + + # @cached_method + def rank(self): + r""" + Return the rank. + + The *rank* of an oriented matroid is the rank of its underlying + matroid. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: A = hyperplane_arrangements.braid(3) + sage: M = OrientedMatroid(A); M.rank() + 2 + sage: A = hyperplane_arrangements.braid(4) + sage: M = OrientedMatroid(A); M.rank() + 3 + """ + return self.matroid().rank() + + def an_element(self): + """ + Returns an arbitrary element. + """ + from sage.misc.prandom import randint + els = self.elements() + i = randint(1, len(els)) + return els[i-1] + + def face_poset(self, facade=False): + r""" + Returns the (big) face poset. + + The *(big) face poset* is the poset on covectors such that `X \leq Y` + if and only if `S(X,Y) = \emptyset` and + `\underline{Y} \subseteq \underline{X}`. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], + ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], + ....: [0,0,0]] + sage: M = OrientedMatroid(C, key='covector') + sage: M.face_poset() + Finite meet-semilattice containing 13 elements + """ + from sage.combinat.posets.lattices import MeetSemilattice + els = self.covectors() + rels = [ + (Y, X) + for X in els + for Y in els + if Y.is_conformal_with(X) and Y.support().issubset(X.support()) + ] + return MeetSemilattice((els, rels), cover_relations=False, facade=facade) + + def face_lattice(self, facade=False): + r""" + Returns the (big) face lattice. + + The *(big) face lattice* is the (big) face poset with a top element + added. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], + ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], + ....: [0,0,0]] + sage: M = OrientedMatroid(C, key='covector') + sage: M.face_lattice() + Finite lattice containing 14 elements + """ + from sage.combinat.posets.lattices import LatticePoset + els = self.covectors() + rels = [ + (Y, X) + for X in els + for Y in els + if Y.is_conformal_with(X) and Y.support().issubset(X.support()) + ] + + # Add top element + for i in els: + rels.append((i, 1)) + els.append(1) + return LatticePoset((els, rels), cover_relations=False, facade=facade) + +# P = self.face_poset() +# rels = P.relations() +# els = [1] +# for i in P: +# els.append(i.element) +# rels.append([i.element, 1]) +# +# return LatticePoset((els,rels), +# cover_relations=False, +# facade=facade) + + def topes(self): + r""" + Returns the topes. + + A *tope* is the maximal covector in the face poset. + """ + return self.face_poset(facade=True).maximal_elements() + + def tope_poset(self, base_tope, facade=False): + r""" + Returns the tope poset. + + The tope poset is the poset `(\mathcal{T}, B)` where `\mathcal{T}` + is the set of topes and `B` is a distinguished tope called the + *base tope*. The order is given by inclusion of separation sets + from the base tope: `X \leq Y` if and only if + `S(B, X) \subseteq S(B, Y)`. + """ + from sage.combinat.posets.posets import Poset + els = self.topes() + rels = [ + (X, Y) + for X in els + for Y in els + if base_tope.separation_set(X).issubset(base_tope.separation_set(Y)) + ] + + return Poset((els, rels), cover_relations=False, facade=facade) + + def is_simplicial(self): + r""" + Returns if the oriented matroid is simplicial. + + An oriented matroid is *simplicial* if every tope is simplicial. + + .. SEEALSO:: + + :meth:`~sage.matroids.oriented_matroids.signed_subset_element.SignedSubsetElement.is_simplicial` + """ + for t in self.topes(): + if not t.is_simplicial(): + return False + return True + + def is_acyclic(self): + r""" + Return if oriented matroid is acyclic. + + A covector oriented matroid is *acyclic* if there exists a positive + tope where a *positive tope* is defined as a tope with no + negative part. + """ + for t in self.topes(): + if len(t.negatives()) == 0: + return True + return False + + def deletion(self, change_set): + r""" + Returns a covector oriented matroid of a deletion. + + Let `M = (E, \mathcal{L})` be an oriented matroid over a set `E` + and a set of covectors `\mathcal{L}`. Given `A \subseteq E`, the + *deletion* is the (covector) oriented matroid + `M\backslash A = (E \backslash A, \mathcal{L} \backslash A)` where + + .. MATH:: + + \mathcal{C} \backslash A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C}\right\} + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + + """ + if change_set in self.groundset(): + change_set = set([change_set]) + else: + change_set = set(change_set) + + from oriented_matroids.oriented_matroid import deep_tupler + groundset = set(self.groundset()).difference(change_set) + groundset = deep_tupler(groundset) + data = [] + for c in self.covectors(): + p = tuple(c.positives().difference(change_set)) + n = tuple(c.negatives().difference(change_set)) + z = tuple(c.zeroes().difference(change_set)) + data.append((p, n, z)) + data = deep_tupler(data) + + from oriented_matroids import OrientedMatroid + return OrientedMatroid(data, key='covector', groundset=groundset) + + def restriction(self, change_set): + r""" + Returns a covector oriented matroid of a restriction. + + Given an oriented matroid `M = (E, \mathcal{L})` where `E` is a + set and `\mathcal{L}` is the set of covectors. Given + `A \subseteq E`, the *restriction* is the (covector) oriented + matroid `M / A = (E \backslash A, \mathcal{C} / A)` where + + .. MATH:: + + \mathcal{C} / A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C} \text{ and} A \subseteq X^0 \right\} + + """ + # sage: from oriented_matroids import OrientedMatroid + # sage: A = hyperplane_arrangements.braid(3) + # sage: M = OrientedMatroid(A); M + # Covector Oriented Matroid of rank 3 + # sage: R = M.restriction(M.groundset()[1]); R + # Covector Oriented Matroid of rank 2 + # sage: R.elements() + # [(0,0), (1,1), (-1,-1)] + if change_set in self.groundset(): + change_set = set([change_set]) + else: + change_set = set(change_set) + + from oriented_matroids.oriented_matroid import deep_tupler + groundset = set(self.groundset()).difference(change_set) + groundset = deep_tupler(groundset) + data = [] + for c in self.covectors(): + p = tuple(c.positives().difference(change_set)) + n = tuple(c.negatives().difference(change_set)) + z = tuple(c.zeroes().difference(change_set)) + if change_set.issubset(c.zeroes()): + data.append((p, n, z)) + data = deep_tupler(data) + + from oriented_matroids import OrientedMatroid + return OrientedMatroid(data, key='covector', groundset=groundset) + + def loops(self): + r""" + Returns the loops of an oriented matroid. + + A *loop* is an element `e \in E` such that there is a + tope `T \in \mathcal{T}` with `T(e) = 0`. In particular + if `T(e) = 0` for some `T`, then it is true for all + `T \in \mathcal{T}`. + """ + T = self.topes()[0] + loops = [] + gs = self.groundset() + for i, j in enumerate(T): + if T(j) == 0: + loops.append(gs[i]) + return loops + + def are_parallel(self, e, f): + r""" + Returns whether two elements in ground set are parallel. + + Two elements in the ground set `e, f \in E` are parallel if they + are not loops and for all `X \in \mathcal{C}`, `X(e) = 0` + implies `X(f) = 0`. See Lemma 4.1.10 [BLSWZ1999]_ . + """ + gs = set(self.groundset()).difference(set(self.loops())) + if e not in gs or f not in gs: + raise ValueError( + "Elements must be in groundset and must not be loops") + for i in self.elements(): + if i(e) == 0 and i(f) != 0: + return False + return True + + def is_simple(self): + r""" + Returns if the oriented matroid is simple. + + An oriented matroid is *simple* if there are no loops + and no parallel elements. + """ + from sage.combinat.subset import Subsets + if len(self.loops()) > 0: + return False + for i in Subsets(self.groundset(), 2): + if self.are_parallel(i[0], i[1]): + return False + return True + + def _element_constructor_(self, x): + r""" + Determine if ``x`` may be viewed as belonging to ``self``. + """ + try: + if x in self.elements(): + return x + return False + except ValueError: + return False diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index fd57f78..942e1b2 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -21,7 +21,7 @@ from sage.structure.parent import Parent from oriented_matroids.covector_oriented_matroid import CovectorOrientedMatroid - +from oriented_matroids.oriented_matroids_category import OrientedMatroids class RealHyperplaneArrangementOrientedMatroid(CovectorOrientedMatroid): r""" @@ -64,20 +64,23 @@ class RealHyperplaneArrangementOrientedMatroid(CovectorOrientedMatroid): """ @staticmethod - def __classcall__(cls, data, groundset=None): + def __classcall__(cls, data, groundset=None, category=None): """ Normalize arguments and set class. """ + if category is None: + category = OrientedMatroids() return super(RealHyperplaneArrangementOrientedMatroid, cls) \ .__classcall__(cls, data=data, - groundset=groundset) + groundset=groundset, + category=category) - def __init__(self, data, groundset=None): + def __init__(self, data, groundset=None, category=None): """ Initialize ``self`` """ - Parent.__init__(self) + Parent.__init__(self, category=category) self._arrangement = data diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index 7a2791b..93ed952 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -19,12 +19,13 @@ # http://www.gnu.org/licenses/ ############################################################################## -from oriented_matroids.abstract_oriented_matriod import AbstractOrientedMatroid +from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent +from oriented_matroids import OrientedMatroids from oriented_matroids.signed_vector_element import SignedVectorElement -class VectorOrientedMatroid(AbstractOrientedMatroid): +class VectorOrientedMatroid(UniqueRepresentation, Parent): r""" An oriented matroid implemented using vector axioms. @@ -80,14 +81,15 @@ def __classcall__(cls, data, groundset=None): """ Normalize arguments and set class. """ + category = OrientedMatroids() return super(VectorOrientedMatroid, cls) \ - .__classcall__(cls, data, groundset=groundset) + .__classcall__(cls, data, groundset=groundset, category=category) - def __init__(self, data, groundset=None): + def __init__(self, data, groundset=None, category=None): """ Initialize ``self``. """ - Parent.__init__(self) + Parent.__init__(self, category=category) # Set up our vectors vectors = [] From 80113a9987e432094ac89e5a824d4e9b77dd9b9c Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Mon, 17 Jul 2023 12:52:48 +0100 Subject: [PATCH 080/101] Delete unnecessary files --- docs/source/oriented_matroids/constructor.rst | 9 - ...yperplane_arrangement_oriented_matroid.rst | 9 - .../abstract_oriented_matroid.py | 548 ------------------ oriented_matroids/constructor.py | 261 --------- 4 files changed, 827 deletions(-) delete mode 100644 docs/source/oriented_matroids/constructor.rst delete mode 100644 docs/source/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.rst delete mode 100644 oriented_matroids/abstract_oriented_matroid.py delete mode 100644 oriented_matroids/constructor.py diff --git a/docs/source/oriented_matroids/constructor.rst b/docs/source/oriented_matroids/constructor.rst deleted file mode 100644 index 3bcf0ac..0000000 --- a/docs/source/oriented_matroids/constructor.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. nodoctest - -Constructor -========================= - -.. automodule:: oriented_matroids.constructor - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.rst b/docs/source/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.rst deleted file mode 100644 index e75557a..0000000 --- a/docs/source/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. nodoctest - -Hyperplane Arrangement Oriented Matroids -======================================== - -.. automodule:: oriented_matroids.hyperplane_arrangement_oriented_matroid - :members: - :undoc-members: - :show-inheritance: diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py deleted file mode 100644 index 221f052..0000000 --- a/oriented_matroids/abstract_oriented_matroid.py +++ /dev/null @@ -1,548 +0,0 @@ -# -*- coding: utf-8 -*- -r""" -Oriented matroids construction - -Theory -====== - -Oriented matroids are ... - -Built-in oriented matroids -========================== - -... - -Constructing oriented matroids -============================== - -To define your own oriented matroid,... - - -AUTHORS: - -- Aram Dermenjian (2019-07-12): initial version - -""" - -# ***************************************************************************** -# Copyright (C) 2019 Aram Dermenjian -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# http://www.gnu.org/licenses/ -# ***************************************************************************** - -from sage.geometry.hyperplane_arrangement.arrangement \ - import HyperplaneArrangementElement -from sage.geometry.triangulation.point_configuration \ - import PointConfiguration -from sage.graphs.digraph import DiGraph -from sage.structure.element import Matrix -import copy -from sage.structure.sage_object import SageObject - - -class AbstractOrientedMatroid(SageObject): - r""" - Construct an oriented matroid. - - The implementation of the oriented matroid differentiates which - axiom set that will be used. - - INPUT: - - - ``groundset`` -- (default: ``None``) is the ground set that will be - used for the oriented matroid. - - - ``data`` -- (default: ``None``) the data that will be used to define - the oriented matroids. It can be one of the following: - - + Objects - - + Hyperplane Arrangement - + Point Configuration - + Digraph - + Matrix (not yet implemented) - - + A list or tuple of - - + :class:`SignedSubsetElement` - + :class:`SignedVectorElement` - + A tuple with positive, negative, and zero sets. - - - ``key`` -- (default: ``None``) is the representation of the - oriented matroid. It can be one of the following: - - + ``'covector'`` - uses covector axioms with covectors - + ``'vector'`` - uses vector axioms with signed subsets - + ``'circuit'`` - uses circuit axioms with signed subsets - + ``None`` - try and guess key. - - Further options: - - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - - sage: A = hyperplane_arrangements.braid(3) - sage: M = OrientedMatroid(A); M - Hyperplane arrangement oriented matroid of rank 2 - sage: M.groundset() - (Hyperplane 0*t0 + t1 - t2 + 0, - Hyperplane t0 - t1 + 0*t2 + 0, - Hyperplane t0 + 0*t1 - t2 + 0) - sage: M.elements() - [(0,0,0), - (0,1,1), - (0,-1,-1), - (1,0,1), - (1,1,1), - (1,-1,0), - (1,-1,1), - (1,-1,-1), - (-1,0,-1), - (-1,1,0), - (-1,1,1), - (-1,1,-1), - (-1,-1,-1)] - - sage: D = DiGraph({'v1':{'v2':1,'v3':2,'v4':3},'v2':{'v3':4,'v4':5},'v3':{'v4':6}}) - sage: M = OrientedMatroid(D,key="circuit"); M - Circuit oriented matroid of rank 3 - sage: len(M.circuits()) - 14 - - sage: PC = PointConfiguration([[1,0,0],[0,1,0],[0,0,1],[1/2,1/2,0],[0,1/2,1/2],[1/3,1/3,1/3]]) - sage: M = OrientedMatroid(PC); M - Circuit oriented matroid of rank 3 - sage: M.matroid() - Matroid of rank 3 on 6 elements with 16 bases - - sage: OrientedMatroid([[0]],key='covector') - Covector oriented matroid of rank 0 - sage: OrientedMatroid([[0]],key='circuit') - Traceback (most recent call last): - ... - ValueError: Empty set not allowed - - OUTPUT: - - An oriented matroid whose axioms are determined by the type. - - .. TODO:: - - - Currently chirotopes are not implemented - - We need a way to go from one type to another - - .. SEEALSO:: - - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` - - REFERENCES: - - For more information see [BLSWZ1999]_ . - - """ - def is_valid(self): - r""" - Return whether satisfies oriented matroid axioms. - - Given a set of objects, this method tests against - a provided set of axioms for a given representation - to ensure that we actually do have an oriented matroid. - """ - pass - - def groundset(self): - """ - Return the ground set of ``self``. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: A = hyperplane_arrangements.braid(2) - sage: M = OrientedMatroid(A); M.groundset() - (Hyperplane t0 - t1 + 0,) - - """ - return self._groundset - - def elements(self): - """ - Return elements. - - The elements of an oriented matroid are the "defining" elements of - the oriented matroid. For example, covectors are the elements of - an oriented matroid defined using covectors. - """ - return self._elements - - def circuits(self): - """ - Return all circuits. - """ - if "_circuits" in dir(self): - return self._circuits - raise NotImplementedError("Circuits not implemented") - - def cocircuits(self): - """ - Return all cocircuits. - """ - if "_cocircuits" in dir(self): - return self._cocircuits - raise NotImplementedError("Cocircuits not implemented") - - def vectors(self): - """ - Return all vectors. - """ - if "_vectors" in dir(self): - return self._vectors - raise NotImplementedError("Vectors not implemented") - pass - - def covectors(self): - """ - Return all covectors. - """ - if "_covectors" in dir(self): - return self._covectors - raise NotImplementedError("Covectors not implemented") - - def to_circuit(self): - """ - Return circuit oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.circuits(), - key='circuit', - groundset=self.groundset()) - - def to_vector(self): - """ - Return vector oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.vectors(), - key='vector', - groundset=self.groundset()) - - def to_covector(self): - """ - Return covector oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.covectors(), - key='covector', - groundset=self.groundset()) - - def dual(self): - """ - Return the dual oriented matroid. - """ - pass - - def matroid(self): - r""" - Returns the underlying matroid. - """ - pass - - def rank(self): - r""" - Return the rank. - - The *rank* of an oriented matroid is the rank of its underlying - matroid. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: A = hyperplane_arrangements.braid(3) - sage: M = OrientedMatroid(A); M.rank() - 2 - sage: A = hyperplane_arrangements.braid(4) - sage: M = OrientedMatroid(A); M.rank() - 3 - """ - return self.matroid().rank() - - def an_element(self): - """ - Returns an arbitrary element. - """ - from sage.misc.prandom import randint - els = self.elements() - i = randint(1, len(els)) - return els[i-1] - - def face_poset(self, facade=False): - r""" - Returns the (big) face poset. - - The *(big) face poset* is the poset on covectors such that `X \leq Y` - if and only if `S(X,Y) = \emptyset` and - `\underline{Y} \subseteq \underline{X}`. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], - ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], - ....: [0,0,0]] - sage: M = OrientedMatroid(C, key='covector') - sage: M.face_poset() - Finite meet-semilattice containing 13 elements - """ - from sage.combinat.posets.lattices import MeetSemilattice - els = self.covectors() - rels = [ - (Y, X) - for X in els - for Y in els - if Y.is_conformal_with(X) and Y.support().issubset(X.support()) - ] - return MeetSemilattice((els, rels), cover_relations=False, facade=facade) - - def face_lattice(self, facade=False): - r""" - Returns the (big) face lattice. - - The *(big) face lattice* is the (big) face poset with a top element - added. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], - ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], - ....: [0,0,0]] - sage: M = OrientedMatroid(C, key='covector') - sage: M.face_lattice() - Finite lattice containing 14 elements - """ - from sage.combinat.posets.lattices import LatticePoset - els = self.covectors() - rels = [ - (Y, X) - for X in els - for Y in els - if Y.is_conformal_with(X) and Y.support().issubset(X.support()) - ] - - # Add top element - for i in els: - rels.append((i, 1)) - els.append(1) - return LatticePoset((els, rels), cover_relations=False, facade=facade) - -# P = self.face_poset() -# rels = P.relations() -# els = [1] -# for i in P: -# els.append(i.element) -# rels.append([i.element, 1]) -# -# return LatticePoset((els,rels), -# cover_relations=False, -# facade=facade) - - def topes(self): - r""" - Returns the topes. - - A *tope* is the maximal covector in the face poset. - """ - return self.face_poset(facade=True).maximal_elements() - - def tope_poset(self, base_tope, facade=False): - r""" - Returns the tope poset. - - The tope poset is the poset `(\mathcal{T}, B)` where `\mathcal{T}` - is the set of topes and `B` is a distinguished tope called the - *base tope*. The order is given by inclusion of separation sets - from the base tope: `X \leq Y` if and only if - `S(B, X) \subseteq S(B, Y)`. - """ - from sage.combinat.posets.posets import Poset - els = self.topes() - rels = [ - (X, Y) - for X in els - for Y in els - if base_tope.separation_set(X).issubset(base_tope.separation_set(Y)) - ] - - return Poset((els, rels), cover_relations=False, facade=facade) - - def is_simplicial(self): - r""" - Returns if the oriented matroid is simplicial. - - An oriented matroid is *simplicial* if every tope is simplicial. - - .. SEEALSO:: - - :meth:`~sage.matroids.oriented_matroids.signed_subset_element.SignedSubsetElement.is_simplicial` - """ - for t in self.topes(): - if not t.is_simplicial(): - return False - return True - - def is_acyclic(self): - r""" - Return if oriented matroid is acyclic. - - A covector oriented matroid is *acyclic* if there exists a positive - tope where a *positive tope* is defined as a tope with no - negative part. - """ - for t in self.topes(): - if len(t.negatives()) == 0: - return True - return False - - def deletion(self, change_set): - r""" - Returns a covector oriented matroid of a deletion. - - Let `M = (E, \mathcal{L})` be an oriented matroid over a set `E` - and a set of covectors `\mathcal{L}`. Given `A \subseteq E`, the - *deletion* is the (covector) oriented matroid - `M\backslash A = (E \backslash A, \mathcal{L} \backslash A)` where - - .. MATH:: - - \mathcal{C} \backslash A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C}\right\} - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - - """ - if change_set in self.groundset(): - change_set = set([change_set]) - else: - change_set = set(change_set) - - from oriented_matroids.oriented_matroid import deep_tupler - groundset = set(self.groundset()).difference(change_set) - groundset = deep_tupler(groundset) - data = [] - for c in self.covectors(): - p = tuple(c.positives().difference(change_set)) - n = tuple(c.negatives().difference(change_set)) - z = tuple(c.zeroes().difference(change_set)) - data.append((p, n, z)) - data = deep_tupler(data) - - from oriented_matroids import OrientedMatroid - return OrientedMatroid(data, key='covector', groundset=groundset) - - def restriction(self, change_set): - r""" - Returns a covector oriented matroid of a restriction. - - Given an oriented matroid `M = (E, \mathcal{L})` where `E` is a - set and `\mathcal{L}` is the set of covectors. Given - `A \subseteq E`, the *restriction* is the (covector) oriented - matroid `M / A = (E \backslash A, \mathcal{C} / A)` where - - .. MATH:: - - \mathcal{C} / A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C} \text{ and} A \subseteq X^0 \right\} - - """ - # sage: from oriented_matroids import OrientedMatroid - # sage: A = hyperplane_arrangements.braid(3) - # sage: M = OrientedMatroid(A); M - # Covector Oriented Matroid of rank 3 - # sage: R = M.restriction(M.groundset()[1]); R - # Covector Oriented Matroid of rank 2 - # sage: R.elements() - # [(0,0), (1,1), (-1,-1)] - if change_set in self.groundset(): - change_set = set([change_set]) - else: - change_set = set(change_set) - - from oriented_matroids.oriented_matroid import deep_tupler - groundset = set(self.groundset()).difference(change_set) - groundset = deep_tupler(groundset) - data = [] - for c in self.covectors(): - p = tuple(c.positives().difference(change_set)) - n = tuple(c.negatives().difference(change_set)) - z = tuple(c.zeroes().difference(change_set)) - if change_set.issubset(c.zeroes()): - data.append((p, n, z)) - data = deep_tupler(data) - - from oriented_matroids import OrientedMatroid - return OrientedMatroid(data, key='covector', groundset=groundset) - - def loops(self): - r""" - Returns the loops of an oriented matroid. - - A *loop* is an element `e \in E` such that there is a - tope `T \in \mathcal{T}` with `T(e) = 0`. In particular - if `T(e) = 0` for some `T`, then it is true for all - `T \in \mathcal{T}`. - """ - T = self.topes()[0] - loops = [] - gs = self.groundset() - for i, j in enumerate(T): - if T(j) == 0: - loops.append(gs[i]) - return loops - - def are_parallel(self, e, f): - r""" - Returns whether two elements in ground set are parallel. - - Two elements in the ground set `e, f \in E` are parallel if they - are not loops and for all `X \in \mathcal{C}`, `X(e) = 0` - implies `X(f) = 0`. See Lemma 4.1.10 [BLSWZ1999]_ . - """ - gs = set(self.groundset()).difference(set(self.loops())) - if e not in gs or f not in gs: - raise ValueError( - "Elements must be in groundset and must not be loops") - for i in self.elements(): - if i(e) == 0 and i(f) != 0: - return False - return True - - def is_simple(self): - r""" - Returns if the oriented matroid is simple. - - An oriented matroid is *simple* if there are no loops - and no parallel elements. - """ - from sage.combinat.subset import Subsets - if len(self.loops()) > 0: - return False - for i in Subsets(self.groundset(), 2): - if self.are_parallel(i[0], i[1]): - return False - return True - - def _element_constructor_(self, x): - r""" - Determine if ``x`` may be viewed as belonging to ``self``. - """ - try: - if x in self.elements(): - return x - return False - except ValueError: - return False \ No newline at end of file diff --git a/oriented_matroids/constructor.py b/oriented_matroids/constructor.py deleted file mode 100644 index a7114bd..0000000 --- a/oriented_matroids/constructor.py +++ /dev/null @@ -1,261 +0,0 @@ -# -*- coding: utf-8 -*- -r""" -Oriented matroids construction - -Theory -====== - -Oriented matroids are ... - -Built-in oriented matroids -========================== - -... - -Constructing oriented matroids -============================== - -To define your own oriented matroid,... - - -AUTHORS: - -- Aram Dermenjian (2019-07-12): initial version - -""" - -# ***************************************************************************** -# Copyright (C) 2019 Aram Dermenjian -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# http://www.gnu.org/licenses/ -# ***************************************************************************** - -from sage.geometry.hyperplane_arrangement.arrangement \ - import HyperplaneArrangementElement -from sage.geometry.triangulation.point_configuration \ - import PointConfiguration -from sage.graphs.digraph import DiGraph -from sage.structure.element import Matrix -import copy - - -def OrientedMatroid(data=None, groundset=None, key=None, **kwds): - r""" - Construct an oriented matroid. - - The implementation of the oriented matroid differentiates which - axiom set that will be used.# - - INPUT: - - - ``groundset`` -- (default: ``None``) is the ground set that will be - used for the oriented matroid. - - - ``data`` -- (default: ``None``) the data that will be used to define - the oriented matroids. It can be one of the following: - - + Objects - - + Hyperplane Arrangement - + Point Configuration - + Digraph - + Matrix (not yet implemented) - - + A list or tuple of - - + :class:`SignedSubsetElement` - + :class:`SignedVectorElement` - + A tuple with positive, negative, and zero sets. - - - ``key`` -- (default: ``None``) is the representation of the - oriented matroid. It can be one of the following: - - + ``'covector'`` - uses covector axioms with covectors - + ``'vector'`` - uses vector axioms with signed subsets - + ``'circuit'`` - uses circuit axioms with signed subsets - + ``None`` - try and guess key. - - Further options: - - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - - sage: A = hyperplane_arrangements.braid(3) - sage: M = OrientedMatroids(A); M - Hyperplane arrangement oriented matroid of rank 2 - sage: M.groundset() - (Hyperplane 0*t0 + t1 - t2 + 0, - Hyperplane t0 - t1 + 0*t2 + 0, - Hyperplane t0 + 0*t1 - t2 + 0) - sage: M.elements() - [(0,0,0), - (0,1,1), - (0,-1,-1), - (1,0,1), - (1,1,1), - (1,-1,0), - (1,-1,1), - (1,-1,-1), - (-1,0,-1), - (-1,1,0), - (-1,1,1), - (-1,1,-1), - (-1,-1,-1)] - - sage: D = DiGraph({'v1':{'v2':1,'v3':2,'v4':3},'v2':{'v3':4,'v4':5},'v3':{'v4':6}}) - sage: M = OrientedMatroid(D,key="circuit"); M - Circuit oriented matroid of rank 3 - sage: len(M.circuits()) - 14 - - sage: PC = PointConfiguration([[1,0,0],[0,1,0],[0,0,1],[1/2,1/2,0],[0,1/2,1/2],[1/3,1/3,1/3]]) - sage: M = OrientedMatroid(PC); M - Circuit oriented matroid of rank 3 - sage: M.matroid() - Matroid of rank 3 on 6 elements with 16 bases - - sage: OrientedMatroid([[0]],key='covector') - Covector oriented matroid of rank 0 - sage: OrientedMatroid([[0]],key='circuit') - Traceback (most recent call last): - ... - ValueError: Empty set not allowed - - OUTPUT: - - An oriented matroid whose axioms are determined by the type. - - .. TODO:: - - - Currently chirotopes are not implemented - - We need a way to go from one type to another - - .. SEEALSO:: - - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` - - REFERENCES: - - For more information see [BLSWZ1999]_ . - - """ - - # Instantiate oriented matroid - OM = None - - # If we have a hyperplane arrangement we need to force the key to be an - # arrangement, - if isinstance(data, HyperplaneArrangementElement): - if key != 'covector' and key is not None: - raise ValueError( - 'Hyperplane arrangements are currently only implemented using covector axioms') - key = 'real_hyperplane_arrangement' - elif isinstance(data, PointConfiguration): - if key != 'circuit' and key is not None: - raise ValueError( - 'Point configurations are currently only implemented using circuit axioms') - key = 'circuit' - # PC circuits are given as (+, 0, -); and only half are given - ci = [(C[0], C[2], C[1]) for C in data.circuits()] - ci += [(C[2], C[0], C[1]) for C in data.circuits()] - data = ci - elif isinstance(data, DiGraph): - if key != 'circuit' and key is not None: - raise ValueError( - 'Digraphs are currently only implemented using circuit axioms') - key = 'circuit' - - # we need to add negative edges in order to do all simple cycles - digraph = copy.copy(data) - edges = copy.copy(list(digraph.edges())) - groundset = [] - if len(edges) != len(set(edges)): - raise ValueError('Edge labels need to be unique') - if None in digraph.edge_labels(): - raise ValueError('Edge labels must be set for all edges') - - # Add minus edges to properly get cycles - for e in edges: - digraph.add_edge(e[1], e[0], "NEG_"+str(e[2])) - groundset.append(str(e[2])) - # Each cycle defines a circuit - data = [] - for c in digraph.all_cycles_iterator(simple=True): - p = set([]) - n = set([]) - for e in range(len(c) - 1): - e = str(digraph.edge_label(c[e], c[e+1])) - if e.startswith('NEG_'): - n.add(e.strip('NEG_')) - else: - p.add(e) - # If an edge exists in both sets, then this is a false cycle. - # This implies we have ee^-1 which is why it's false. - # So we only add the true ones. - if len(p.intersection(n)) == 0: - data.append([p, n]) - elif isinstance(data, Matrix): - if key != 'chirotope' and key is not None: - raise ValueError( - 'Matrices are currently only implemented using chirotope axioms') - key = 'chirotope' - - if key not in OrientedMatroids.keys: - raise ValueError("invalid type key") - - # In the following cases, deep_tupler is used since we are using - # UniqueRepresentation Which doesn't allow us to have non-hashable things. - if key == "covector": - from oriented_matroids.covector_oriented_matroid \ - import CovectorOrientedMatroid - data = deep_tupler(data) - if groundset is not None: - groundset = deep_tupler(groundset) - OM = CovectorOrientedMatroid(data, groundset=groundset) - elif key == "circuit": - from oriented_matroids.circuit_oriented_matroid \ - import CircuitOrientedMatroid - data = deep_tupler(data) - if groundset is not None: - groundset = deep_tupler(groundset) - OM = CircuitOrientedMatroid(data, groundset=groundset) - elif key == "vector": - from oriented_matroids.vector_oriented_matroid \ - import VectorOrientedMatroid - data = deep_tupler(data) - if groundset is not None: - groundset = deep_tupler(groundset) - OM = VectorOrientedMatroid(data, groundset=groundset) - elif key == "real_hyperplane_arrangement": - from oriented_matroids.real_hyperplane_arrangement_oriented_matroid \ - import RealHyperplaneArrangementOrientedMatroid - A = copy.copy(data) - if groundset is None: - groundset = deep_tupler(A.hyperplanes()) - else: - groundset = deep_tupler(groundset) - OM = RealHyperplaneArrangementOrientedMatroid(A, groundset=groundset) - - if OM is None: - raise NotImplementedError( - "Oriented matroid of type {} is not implemented".format(key)) - - if OM.is_valid(): - return OM - - raise ValueError("Oriented matroid is not valid") - - -def deep_tupler(obj): - r""" - changes a (nested) list or set into a (nested) tuple to be hashable - """ - if isinstance(obj, list) or isinstance(obj, set): - return tuple([deep_tupler(i) for i in obj]) - return obj \ No newline at end of file From 51e801950f2fd58cd12287d8b34fb885c43f4eba Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Mon, 17 Jul 2023 14:32:14 +0100 Subject: [PATCH 081/101] Make sage doctests work --- oriented_matroids/oriented_matroid.py | 2 +- .../real_hyperplane_arrangement_oriented_matroid.py | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 0321e64..000112c 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -174,7 +174,7 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): # we need to add negative edges in order to do all simple cycles digraph = copy.copy(data) - edges = copy.copy(list(digraph.edges())) + edges = copy.copy(list(digraph.edges(sort=True))) groundset = [] if len(edges) != len(set(edges)): raise ValueError('Edge labels need to be unique') diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index c78c27f..a682157 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -80,23 +80,16 @@ def __init__(self, data, groundset=None, category=None): """ Initialize ``self`` """ - Parent.__init__(self, category=category) self._arrangement = data if data and groundset is None: groundset = tuple(data.hyperplanes()) - if groundset is None: - self._groundset = groundset - else: - self._groundset = tuple(groundset) - # Set up our covectors after our groundset is made faces = [i[0] for i in self._arrangement.closed_faces()] - self._covectors = [self.element_class( - self, data=f, groundset=self._groundset) for f in faces] - self._elements = self._covectors + + CovectorOrientedMatroid.__init__(self, data=faces, groundset=groundset, category=category) def _repr_(self): """ From 41ce3d9382964fafa8dfece290e5a4ae63576e8c Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Mon, 17 Jul 2023 15:27:53 +0100 Subject: [PATCH 082/101] Update structure to match Tableaux --- .../abstract_oriented_matroid.py | 475 +++++++++++++++++ oriented_matroids/circuit_oriented_matroid.py | 16 +- .../covector_oriented_matroid.py | 13 +- .../oriented_matroids_category.py | 479 ------------------ oriented_matroids/vector_oriented_matroid.py | 16 +- 5 files changed, 494 insertions(+), 505 deletions(-) create mode 100644 oriented_matroids/abstract_oriented_matroid.py delete mode 100644 oriented_matroids/oriented_matroids_category.py diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py new file mode 100644 index 0000000..20ce652 --- /dev/null +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -0,0 +1,475 @@ +# -*- coding: utf-8 -*- +r""" +Category of Oriented Matroids +""" +# ***************************************************************************** +# Copyright (C) 2019 Aram Dermenjian +# +# Distributed under the terms of the GNU General Public License (GPL) +# http://www.gnu.org/licenses/ +# ****************************************************************************** + +from sage.misc.abstract_method import abstract_method +from sage.misc.cachefunc import cached_method +from sage.structure.unique_representation import UniqueRepresentation +from sage.structure.parent import Parent +from sage.categories.sets_cat import Sets +from oriented_matroids.signed_subset_element import SignedSubsetElement + + +class AbstractOrientedMatroid(UniqueRepresentation, Parent): + r""" + The category of oriented matroids. + + Given a set `E` a signed subset of `E` is a pair `X = (X^+,X^-)` where + `X^+,X^- \subseteq E` and `X^+ \cap X^- = \emptyset`. The support of `X` + is the set `\underline{X} = X^+ \cup X^-`. An *oriented matroid* is a + pair `M = (E,\mathcal{C})` where `E` is a set and `\mathcal{C}` is a + collection of signed subsets of `E` that satisfy certain axioms. An example + of these axioms are the circuit axioms: + + - `\emptyset \not\in \mathcal{C}` + - `\mathcal{C}= -\mathcal{C}` + - for all `X,Y \in \mathcal{C}`, + if `\underline{X} \subseteq \underline{Y}` then `X = Y` or `X = -Y`. + - for all `X,Y \in \mathcal{C}`, `X \neq -Y`, and `e \in X^+ \cap Y^-` + there is a `Z \in \mathcal{C}` such that + `Z^+ \subseteq \left(X^+ \cup Y^+\right) \backslash \left\{e\right\}` + and + `Z^- \subseteq \left(X^- \cup Y^-\right) \backslash \left\{e\right\}`. + + See :wikipedia:`Oriented_matroid` for details. + + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroids + sage: M = OrientedMatroids(); M + Category of oriented matroids + sage: M.super_categories() + [Category of sets] + + .. SEEALSO:: + + :class:`oriented_matroids.oriented_matroid.OrientedMatroid` + + TESTS:: + + sage: TestSuite(M).run() + """ + + """ + List of all possible keys + """ + keys = ['circuit', 'covector', 'vector', 'real_hyperplane_arrangement'] + + Element = SignedSubsetElement + + def __init__(self, category=None): + if category is None: + category = Sets() + Parent.__init__(self, category=category) + + @abstract_method + def is_valid(self): + r""" + Return whether satisfies oriented matroid axioms. + + Given a set of objects, this method tests against + a provided set of axioms for a given representation + to ensure that we actually do have an oriented matroid. + """ + pass + + def groundset(self): + """ + Return the ground set of ``self``. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: A = hyperplane_arrangements.braid(2) + sage: M = OrientedMatroid(A); M.groundset() + (Hyperplane t0 - t1 + 0,) + + """ + return self._groundset + + def elements(self): + """ + Return elements. + + The elements of an oriented matroid are the "defining" elements of + the oriented matroid. For example, covectors are the elements of + an oriented matroid defined using covectors. + """ + return self._elements + + def circuits(self): + """ + Return all circuits. + """ + if "_circuits" in dir(self): + return self._circuits + raise NotImplementedError("Circuits not implemented") + + def cocircuits(self): + """ + Return all cocircuits. + """ + if "_cocircuits" in dir(self): + return self._cocircuits + raise NotImplementedError("Cocircuits not implemented") + + def vectors(self): + """ + Return all vectors. + """ + if "_vectors" in dir(self): + return self._vectors + raise NotImplementedError("Vectors not implemented") + pass + + def covectors(self): + """ + Return all covectors. + """ + if "_covectors" in dir(self): + return self._covectors + raise NotImplementedError("Covectors not implemented") + + def to_circuit(self): + """ + Return circuit oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.circuits(), + key='circuit', + groundset=self.groundset()) + + def to_vector(self): + """ + Return vector oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.vectors(), + key='vector', + groundset=self.groundset()) + + def to_covector(self): + """ + Return covector oriented matroid. + """ + from oriented_matroids import OrientedMatroid + return OrientedMatroid(self.covectors(), + key='covector', + groundset=self.groundset()) + + def dual(self): + """ + Return the dual oriented matroid. + """ + pass + + @cached_method + def matroid(self): + r""" + Returns the underlying matroid. + """ + pass + + # @cached_method + def rank(self): + r""" + Return the rank. + + The *rank* of an oriented matroid is the rank of its underlying + matroid. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: A = hyperplane_arrangements.braid(3) + sage: M = OrientedMatroid(A); M.rank() + 2 + sage: A = hyperplane_arrangements.braid(4) + sage: M = OrientedMatroid(A); M.rank() + 3 + """ + return self.matroid().rank() + + def an_element(self): + """ + Returns an arbitrary element. + """ + from sage.misc.prandom import randint + els = self.elements() + i = randint(1, len(els)) + return els[i-1] + + def face_poset(self, facade=False): + r""" + Returns the (big) face poset. + + The *(big) face poset* is the poset on covectors such that `X \leq Y` + if and only if `S(X,Y) = \emptyset` and + `\underline{Y} \subseteq \underline{X}`. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], + ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], + ....: [0,0,0]] + sage: M = OrientedMatroid(C, key='covector') + sage: M.face_poset() + Finite meet-semilattice containing 13 elements + """ + from sage.combinat.posets.lattices import MeetSemilattice + els = self.covectors() + rels = [ + (Y, X) + for X in els + for Y in els + if Y.is_conformal_with(X) and Y.support().issubset(X.support()) + ] + return MeetSemilattice((els, rels), cover_relations=False, facade=facade) + + def face_lattice(self, facade=False): + r""" + Returns the (big) face lattice. + + The *(big) face lattice* is the (big) face poset with a top element + added. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], + ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], + ....: [0,0,0]] + sage: M = OrientedMatroid(C, key='covector') + sage: M.face_lattice() + Finite lattice containing 14 elements + """ + from sage.combinat.posets.lattices import LatticePoset + els = self.covectors() + rels = [ + (Y, X) + for X in els + for Y in els + if Y.is_conformal_with(X) and Y.support().issubset(X.support()) + ] + + # Add top element + for i in els: + rels.append((i, 1)) + els.append(1) + return LatticePoset((els, rels), cover_relations=False, facade=facade) + +# P = self.face_poset() +# rels = P.relations() +# els = [1] +# for i in P: +# els.append(i.element) +# rels.append([i.element, 1]) +# +# return LatticePoset((els,rels), +# cover_relations=False, +# facade=facade) + + def topes(self): + r""" + Returns the topes. + + A *tope* is the maximal covector in the face poset. + """ + return self.face_poset(facade=True).maximal_elements() + + def tope_poset(self, base_tope, facade=False): + r""" + Returns the tope poset. + + The tope poset is the poset `(\mathcal{T}, B)` where `\mathcal{T}` + is the set of topes and `B` is a distinguished tope called the + *base tope*. The order is given by inclusion of separation sets + from the base tope: `X \leq Y` if and only if + `S(B, X) \subseteq S(B, Y)`. + """ + from sage.combinat.posets.posets import Poset + els = self.topes() + rels = [ + (X, Y) + for X in els + for Y in els + if base_tope.separation_set(X).issubset(base_tope.separation_set(Y)) + ] + + return Poset((els, rels), cover_relations=False, facade=facade) + + def is_simplicial(self): + r""" + Returns if the oriented matroid is simplicial. + + An oriented matroid is *simplicial* if every tope is simplicial. + + .. SEEALSO:: + + :meth:`~sage.matroids.oriented_matroids.signed_subset_element.SignedSubsetElement.is_simplicial` + """ + for t in self.topes(): + if not t.is_simplicial(): + return False + return True + + def is_acyclic(self): + r""" + Return if oriented matroid is acyclic. + + A covector oriented matroid is *acyclic* if there exists a positive + tope where a *positive tope* is defined as a tope with no + negative part. + """ + for t in self.topes(): + if len(t.negatives()) == 0: + return True + return False + + def deletion(self, change_set): + r""" + Returns a covector oriented matroid of a deletion. + + Let `M = (E, \mathcal{L})` be an oriented matroid over a set `E` + and a set of covectors `\mathcal{L}`. Given `A \subseteq E`, the + *deletion* is the (covector) oriented matroid + `M\backslash A = (E \backslash A, \mathcal{L} \backslash A)` where + + .. MATH:: + + \mathcal{C} \backslash A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C}\right\} + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + + """ + if change_set in self.groundset(): + change_set = set([change_set]) + else: + change_set = set(change_set) + + from oriented_matroids.oriented_matroid import deep_tupler + groundset = set(self.groundset()).difference(change_set) + groundset = deep_tupler(groundset) + data = [] + for c in self.covectors(): + p = tuple(c.positives().difference(change_set)) + n = tuple(c.negatives().difference(change_set)) + z = tuple(c.zeroes().difference(change_set)) + data.append((p, n, z)) + data = deep_tupler(data) + + from oriented_matroids import OrientedMatroid + return OrientedMatroid(data, key='covector', groundset=groundset) + + def restriction(self, change_set): + r""" + Returns a covector oriented matroid of a restriction. + + Given an oriented matroid `M = (E, \mathcal{L})` where `E` is a + set and `\mathcal{L}` is the set of covectors. Given + `A \subseteq E`, the *restriction* is the (covector) oriented + matroid `M / A = (E \backslash A, \mathcal{C} / A)` where + + .. MATH:: + + \mathcal{C} / A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C} \text{ and} A \subseteq X^0 \right\} + + """ + # sage: from oriented_matroids import OrientedMatroid + # sage: A = hyperplane_arrangements.braid(3) + # sage: M = OrientedMatroid(A); M + # Covector Oriented Matroid of rank 3 + # sage: R = M.restriction(M.groundset()[1]); R + # Covector Oriented Matroid of rank 2 + # sage: R.elements() + # [(0,0), (1,1), (-1,-1)] + if change_set in self.groundset(): + change_set = set([change_set]) + else: + change_set = set(change_set) + + from oriented_matroids.oriented_matroid import deep_tupler + groundset = set(self.groundset()).difference(change_set) + groundset = deep_tupler(groundset) + data = [] + for c in self.covectors(): + p = tuple(c.positives().difference(change_set)) + n = tuple(c.negatives().difference(change_set)) + z = tuple(c.zeroes().difference(change_set)) + if change_set.issubset(c.zeroes()): + data.append((p, n, z)) + data = deep_tupler(data) + + from oriented_matroids import OrientedMatroid + return OrientedMatroid(data, key='covector', groundset=groundset) + + def loops(self): + r""" + Returns the loops of an oriented matroid. + + A *loop* is an element `e \in E` such that there is a + tope `T \in \mathcal{T}` with `T(e) = 0`. In particular + if `T(e) = 0` for some `T`, then it is true for all + `T \in \mathcal{T}`. + """ + T = self.topes()[0] + loops = [] + gs = self.groundset() + for i, j in enumerate(T): + if T(j) == 0: + loops.append(gs[i]) + return loops + + def are_parallel(self, e, f): + r""" + Returns whether two elements in ground set are parallel. + + Two elements in the ground set `e, f \in E` are parallel if they + are not loops and for all `X \in \mathcal{C}`, `X(e) = 0` + implies `X(f) = 0`. See Lemma 4.1.10 [BLSWZ1999]_ . + """ + gs = set(self.groundset()).difference(set(self.loops())) + if e not in gs or f not in gs: + raise ValueError( + "Elements must be in groundset and must not be loops") + for i in self.elements(): + if i(e) == 0 and i(f) != 0: + return False + return True + + def is_simple(self): + r""" + Returns if the oriented matroid is simple. + + An oriented matroid is *simple* if there are no loops + and no parallel elements. + """ + from sage.combinat.subset import Subsets + if len(self.loops()) > 0: + return False + for i in Subsets(self.groundset(), 2): + if self.are_parallel(i[0], i[1]): + return False + return True + + def _element_constructor_(self, x): + r""" + Determine if ``x`` may be viewed as belonging to ``self``. + """ + try: + if x in self.elements(): + return x + return False + except ValueError: + return False diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index eb562dd..b911b9f 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -19,13 +19,12 @@ # http://www.gnu.org/licenses/ ############################################################################## -from sage.structure.unique_representation import UniqueRepresentation -from sage.structure.parent import Parent -from oriented_matroids.oriented_matroids_category import OrientedMatroids +from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid from oriented_matroids.signed_subset_element import SignedSubsetElement +from sage.categories.sets_cat import Sets -class CircuitOrientedMatroid(UniqueRepresentation, Parent): +class CircuitOrientedMatroid(AbstractOrientedMatroid): r""" An oriented matroid implemented using circuit axioms. @@ -69,15 +68,14 @@ class CircuitOrientedMatroid(UniqueRepresentation, Parent): :class:`oriented_matroids.oriented_matroid.OrientedMatroid` :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` """ - Element = SignedSubsetElement @staticmethod - def __classcall__(cls, data, groundset=None): + def __classcall__(cls, data, groundset=None, category=None): """ Normalize arguments and set class. """ - - category = OrientedMatroids() + if category is None: + category = Sets() return super(CircuitOrientedMatroid, cls) \ .__classcall__(cls, data=data, @@ -88,7 +86,7 @@ def __init__(self, data, groundset=None, category=None): """ Initialize ``self``. """ - Parent.__init__(self, category=category) + AbstractOrientedMatroid.__init__(self, category=category) # Set up our circuits circuits = [] diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 7a08dda..111c8b0 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -19,15 +19,14 @@ # http://www.gnu.org/licenses/ ############################################################################## -from sage.structure.unique_representation import UniqueRepresentation -from sage.structure.parent import Parent -from oriented_matroids.oriented_matroids_category import OrientedMatroids +from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid from oriented_matroids.signed_vector_element import SignedVectorElement +from sage.categories.sets_cat import Sets import copy -class CovectorOrientedMatroid(UniqueRepresentation, Parent): +class CovectorOrientedMatroid(AbstractOrientedMatroid): r""" An oriented matroid implemented using covector axioms. @@ -80,15 +79,13 @@ class CovectorOrientedMatroid(UniqueRepresentation, Parent): :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` """ - Element = SignedVectorElement - @staticmethod def __classcall__(cls, data, groundset=None, category=None): """ Normalize arguments and set class. """ if category is None: - category = OrientedMatroids() + category = Sets() return super(CovectorOrientedMatroid, cls) \ .__classcall__(cls, data, groundset=groundset, category=category) @@ -96,7 +93,7 @@ def __init__(self, data, groundset=None, category=None): """ Initialize ``self`` """ - Parent.__init__(self, category=category) + AbstractOrientedMatroid.__init__(self, category=category) # Set up our covectors covectors = [] diff --git a/oriented_matroids/oriented_matroids_category.py b/oriented_matroids/oriented_matroids_category.py deleted file mode 100644 index 2ceb748..0000000 --- a/oriented_matroids/oriented_matroids_category.py +++ /dev/null @@ -1,479 +0,0 @@ -# -*- coding: utf-8 -*- -r""" -Category of Oriented Matroids -""" -# ***************************************************************************** -# Copyright (C) 2019 Aram Dermenjian -# -# Distributed under the terms of the GNU General Public License (GPL) -# http://www.gnu.org/licenses/ -# ****************************************************************************** - -from sage.misc.abstract_method import abstract_method -from sage.misc.cachefunc import cached_method -from sage.categories.category import Category -from sage.categories.sets_cat import Sets - - -class OrientedMatroids(Category): - r""" - The category of oriented matroids. - - Given a set `E` a signed subset of `E` is a pair `X = (X^+,X^-)` where - `X^+,X^- \subseteq E` and `X^+ \cap X^- = \emptyset`. The support of `X` - is the set `\underline{X} = X^+ \cup X^-`. An *oriented matroid* is a - pair `M = (E,\mathcal{C})` where `E` is a set and `\mathcal{C}` is a - collection of signed subsets of `E` that satisfy certain axioms. An example - of these axioms are the circuit axioms: - - - `\emptyset \not\in \mathcal{C}` - - `\mathcal{C}= -\mathcal{C}` - - for all `X,Y \in \mathcal{C}`, - if `\underline{X} \subseteq \underline{Y}` then `X = Y` or `X = -Y`. - - for all `X,Y \in \mathcal{C}`, `X \neq -Y`, and `e \in X^+ \cap Y^-` - there is a `Z \in \mathcal{C}` such that - `Z^+ \subseteq \left(X^+ \cup Y^+\right) \backslash \left\{e\right\}` - and - `Z^- \subseteq \left(X^- \cup Y^-\right) \backslash \left\{e\right\}`. - - See :wikipedia:`Oriented_matroid` for details. - - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroids - sage: M = OrientedMatroids(); M - Category of oriented matroids - sage: M.super_categories() - [Category of sets] - - .. SEEALSO:: - - :class:`oriented_matroids.oriented_matroid.OrientedMatroid` - - TESTS:: - - sage: TestSuite(M).run() - """ - - """ - List of all possible keys - """ - keys = ['circuit', 'covector', 'vector', 'real_hyperplane_arrangement'] - - @cached_method - def super_categories(self): - """ - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroids - sage: OrientedMatroids().super_categories() - [Category of sets] - """ - return [Sets()] - - class ParentMethods: - - @abstract_method - def is_valid(self): - r""" - Return whether satisfies oriented matroid axioms. - - Given a set of objects, this method tests against - a provided set of axioms for a given representation - to ensure that we actually do have an oriented matroid. - """ - pass - - def groundset(self): - """ - Return the ground set of ``self``. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: A = hyperplane_arrangements.braid(2) - sage: M = OrientedMatroid(A); M.groundset() - (Hyperplane t0 - t1 + 0,) - - """ - return self._groundset - - def elements(self): - """ - Return elements. - - The elements of an oriented matroid are the "defining" elements of - the oriented matroid. For example, covectors are the elements of - an oriented matroid defined using covectors. - """ - return self._elements - - def circuits(self): - """ - Return all circuits. - """ - if "_circuits" in dir(self): - return self._circuits - raise NotImplementedError("Circuits not implemented") - - def cocircuits(self): - """ - Return all cocircuits. - """ - if "_cocircuits" in dir(self): - return self._cocircuits - raise NotImplementedError("Cocircuits not implemented") - - def vectors(self): - """ - Return all vectors. - """ - if "_vectors" in dir(self): - return self._vectors - raise NotImplementedError("Vectors not implemented") - pass - - def covectors(self): - """ - Return all covectors. - """ - if "_covectors" in dir(self): - return self._covectors - raise NotImplementedError("Covectors not implemented") - - def to_circuit(self): - """ - Return circuit oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.circuits(), - key='circuit', - groundset=self.groundset()) - - def to_vector(self): - """ - Return vector oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.vectors(), - key='vector', - groundset=self.groundset()) - - def to_covector(self): - """ - Return covector oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.covectors(), - key='covector', - groundset=self.groundset()) - - def dual(self): - """ - Return the dual oriented matroid. - """ - pass - - @cached_method - def matroid(self): - r""" - Returns the underlying matroid. - """ - pass - - # @cached_method - def rank(self): - r""" - Return the rank. - - The *rank* of an oriented matroid is the rank of its underlying - matroid. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: A = hyperplane_arrangements.braid(3) - sage: M = OrientedMatroid(A); M.rank() - 2 - sage: A = hyperplane_arrangements.braid(4) - sage: M = OrientedMatroid(A); M.rank() - 3 - """ - return self.matroid().rank() - - def an_element(self): - """ - Returns an arbitrary element. - """ - from sage.misc.prandom import randint - els = self.elements() - i = randint(1, len(els)) - return els[i-1] - - def face_poset(self, facade=False): - r""" - Returns the (big) face poset. - - The *(big) face poset* is the poset on covectors such that `X \leq Y` - if and only if `S(X,Y) = \emptyset` and - `\underline{Y} \subseteq \underline{X}`. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], - ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], - ....: [0,0,0]] - sage: M = OrientedMatroid(C, key='covector') - sage: M.face_poset() - Finite meet-semilattice containing 13 elements - """ - from sage.combinat.posets.lattices import MeetSemilattice - els = self.covectors() - rels = [ - (Y, X) - for X in els - for Y in els - if Y.is_conformal_with(X) and Y.support().issubset(X.support()) - ] - return MeetSemilattice((els, rels), cover_relations=False, facade=facade) - - def face_lattice(self, facade=False): - r""" - Returns the (big) face lattice. - - The *(big) face lattice* is the (big) face poset with a top element - added. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], - ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], - ....: [0,0,0]] - sage: M = OrientedMatroid(C, key='covector') - sage: M.face_lattice() - Finite lattice containing 14 elements - """ - from sage.combinat.posets.lattices import LatticePoset - els = self.covectors() - rels = [ - (Y, X) - for X in els - for Y in els - if Y.is_conformal_with(X) and Y.support().issubset(X.support()) - ] - - # Add top element - for i in els: - rels.append((i, 1)) - els.append(1) - return LatticePoset((els, rels), cover_relations=False, facade=facade) - -# P = self.face_poset() -# rels = P.relations() -# els = [1] -# for i in P: -# els.append(i.element) -# rels.append([i.element, 1]) -# -# return LatticePoset((els,rels), -# cover_relations=False, -# facade=facade) - - def topes(self): - r""" - Returns the topes. - - A *tope* is the maximal covector in the face poset. - """ - return self.face_poset(facade=True).maximal_elements() - - def tope_poset(self, base_tope, facade=False): - r""" - Returns the tope poset. - - The tope poset is the poset `(\mathcal{T}, B)` where `\mathcal{T}` - is the set of topes and `B` is a distinguished tope called the - *base tope*. The order is given by inclusion of separation sets - from the base tope: `X \leq Y` if and only if - `S(B, X) \subseteq S(B, Y)`. - """ - from sage.combinat.posets.posets import Poset - els = self.topes() - rels = [ - (X, Y) - for X in els - for Y in els - if base_tope.separation_set(X).issubset(base_tope.separation_set(Y)) - ] - - return Poset((els, rels), cover_relations=False, facade=facade) - - def is_simplicial(self): - r""" - Returns if the oriented matroid is simplicial. - - An oriented matroid is *simplicial* if every tope is simplicial. - - .. SEEALSO:: - - :meth:`~sage.matroids.oriented_matroids.signed_subset_element.SignedSubsetElement.is_simplicial` - """ - for t in self.topes(): - if not t.is_simplicial(): - return False - return True - - def is_acyclic(self): - r""" - Return if oriented matroid is acyclic. - - A covector oriented matroid is *acyclic* if there exists a positive - tope where a *positive tope* is defined as a tope with no - negative part. - """ - for t in self.topes(): - if len(t.negatives()) == 0: - return True - return False - - def deletion(self, change_set): - r""" - Returns a covector oriented matroid of a deletion. - - Let `M = (E, \mathcal{L})` be an oriented matroid over a set `E` - and a set of covectors `\mathcal{L}`. Given `A \subseteq E`, the - *deletion* is the (covector) oriented matroid - `M\backslash A = (E \backslash A, \mathcal{L} \backslash A)` where - - .. MATH:: - - \mathcal{C} \backslash A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C}\right\} - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - - """ - if change_set in self.groundset(): - change_set = set([change_set]) - else: - change_set = set(change_set) - - from oriented_matroids.oriented_matroid import deep_tupler - groundset = set(self.groundset()).difference(change_set) - groundset = deep_tupler(groundset) - data = [] - for c in self.covectors(): - p = tuple(c.positives().difference(change_set)) - n = tuple(c.negatives().difference(change_set)) - z = tuple(c.zeroes().difference(change_set)) - data.append((p, n, z)) - data = deep_tupler(data) - - from oriented_matroids import OrientedMatroid - return OrientedMatroid(data, key='covector', groundset=groundset) - - def restriction(self, change_set): - r""" - Returns a covector oriented matroid of a restriction. - - Given an oriented matroid `M = (E, \mathcal{L})` where `E` is a - set and `\mathcal{L}` is the set of covectors. Given - `A \subseteq E`, the *restriction* is the (covector) oriented - matroid `M / A = (E \backslash A, \mathcal{C} / A)` where - - .. MATH:: - - \mathcal{C} / A = \left\{ X\mid_{E \backslash A} : X \in \mathcal{C} \text{ and} A \subseteq X^0 \right\} - - """ - # sage: from oriented_matroids import OrientedMatroid - # sage: A = hyperplane_arrangements.braid(3) - # sage: M = OrientedMatroid(A); M - # Covector Oriented Matroid of rank 3 - # sage: R = M.restriction(M.groundset()[1]); R - # Covector Oriented Matroid of rank 2 - # sage: R.elements() - # [(0,0), (1,1), (-1,-1)] - if change_set in self.groundset(): - change_set = set([change_set]) - else: - change_set = set(change_set) - - from oriented_matroids.oriented_matroid import deep_tupler - groundset = set(self.groundset()).difference(change_set) - groundset = deep_tupler(groundset) - data = [] - for c in self.covectors(): - p = tuple(c.positives().difference(change_set)) - n = tuple(c.negatives().difference(change_set)) - z = tuple(c.zeroes().difference(change_set)) - if change_set.issubset(c.zeroes()): - data.append((p, n, z)) - data = deep_tupler(data) - - from oriented_matroids import OrientedMatroid - return OrientedMatroid(data, key='covector', groundset=groundset) - - def loops(self): - r""" - Returns the loops of an oriented matroid. - - A *loop* is an element `e \in E` such that there is a - tope `T \in \mathcal{T}` with `T(e) = 0`. In particular - if `T(e) = 0` for some `T`, then it is true for all - `T \in \mathcal{T}`. - """ - T = self.topes()[0] - loops = [] - gs = self.groundset() - for i, j in enumerate(T): - if T(j) == 0: - loops.append(gs[i]) - return loops - - def are_parallel(self, e, f): - r""" - Returns whether two elements in ground set are parallel. - - Two elements in the ground set `e, f \in E` are parallel if they - are not loops and for all `X \in \mathcal{C}`, `X(e) = 0` - implies `X(f) = 0`. See Lemma 4.1.10 [BLSWZ1999]_ . - """ - gs = set(self.groundset()).difference(set(self.loops())) - if e not in gs or f not in gs: - raise ValueError( - "Elements must be in groundset and must not be loops") - for i in self.elements(): - if i(e) == 0 and i(f) != 0: - return False - return True - - def is_simple(self): - r""" - Returns if the oriented matroid is simple. - - An oriented matroid is *simple* if there are no loops - and no parallel elements. - """ - from sage.combinat.subset import Subsets - if len(self.loops()) > 0: - return False - for i in Subsets(self.groundset(), 2): - if self.are_parallel(i[0], i[1]): - return False - return True - - def _element_constructor_(self, x): - r""" - Determine if ``x`` may be viewed as belonging to ``self``. - """ - try: - if x in self.elements(): - return x - return False - except ValueError: - return False diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index 93ed952..a1c3a0d 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -19,13 +19,12 @@ # http://www.gnu.org/licenses/ ############################################################################## -from sage.structure.unique_representation import UniqueRepresentation -from sage.structure.parent import Parent -from oriented_matroids import OrientedMatroids +from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid from oriented_matroids.signed_vector_element import SignedVectorElement +from sage.categories.sets_cat import Sets -class VectorOrientedMatroid(UniqueRepresentation, Parent): +class VectorOrientedMatroid(AbstractOrientedMatroid): r""" An oriented matroid implemented using vector axioms. @@ -74,14 +73,13 @@ class VectorOrientedMatroid(UniqueRepresentation, Parent): - :class:`oriented_matroids.oriented_matroid.OrientedMatroid` - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` """ - Element = SignedVectorElement - @staticmethod - def __classcall__(cls, data, groundset=None): + def __classcall__(cls, data, groundset=None, category=None): """ Normalize arguments and set class. """ - category = OrientedMatroids() + if category is None: + category = Sets() return super(VectorOrientedMatroid, cls) \ .__classcall__(cls, data, groundset=groundset, category=category) @@ -89,7 +87,7 @@ def __init__(self, data, groundset=None, category=None): """ Initialize ``self``. """ - Parent.__init__(self, category=category) + AbstractOrientedMatroid.__init__(self, category=category) # Set up our vectors vectors = [] From 7377aec37a05fd675385a076649da99d1437c93c Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Mon, 17 Jul 2023 16:03:07 +0100 Subject: [PATCH 083/101] Add global options --- oriented_matroids/__init__.py | 2 +- .../abstract_oriented_matroid.py | 617 +++++++++++++++++- oriented_matroids/all.py | 2 +- oriented_matroids/circuit_oriented_matroid.py | 1 - .../covector_oriented_matroid.py | 1 - oriented_matroids/oriented_matroid.py | 2 + oriented_matroids/signed_subset_element.py | 569 ---------------- oriented_matroids/signed_vector_element.py | 121 ---- oriented_matroids/vector_oriented_matroid.py | 1 - 9 files changed, 607 insertions(+), 709 deletions(-) delete mode 100644 oriented_matroids/signed_subset_element.py delete mode 100644 oriented_matroids/signed_vector_element.py diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py index 7ad0a4b..af8d503 100644 --- a/oriented_matroids/__init__.py +++ b/oriented_matroids/__init__.py @@ -1,6 +1,6 @@ from __future__ import absolute_import from .oriented_matroid import OrientedMatroid -from .oriented_matroids_category import OrientedMatroids +from .abstract_oriented_matroid import AbstractOrientedMatroid from sage.misc.lazy_import import lazy_import #lazy_import('sage.matroids.oriented_matroids', diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py index 20ce652..698e247 100644 --- a/oriented_matroids/abstract_oriented_matroid.py +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -14,9 +14,589 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent from sage.categories.sets_cat import Sets -from oriented_matroids.signed_subset_element import SignedSubsetElement +from sage.structure.global_options import GlobalOptions +from sage.structure.element import Element +import copy + +r""" +Signed Subset element +--------------------------------------- + +This implements a basic signed subet element which is used for oriented +matroids. + +AUTHORS: + +- Aram Dermenjian (2019-07-12): Initial version +""" + +############################################################################## +# Copyright (C) 2019 Aram Dermenjian +# +# Distributed under the terms of the GNU General Public License (GPL) +# +# The full text of the GPL is available at: +# +# http://www.gnu.org/licenses/ +############################################################################## + + +class SignedSubsetElement(Element): + r""" + Creates a signed subset. + + INPUT: + + - ``parent`` -- the parent object of the element. Usually is a class + generated by :class:`OrientedMatroid`. + - ``data`` -- (default: ``None``) is a tuple with information. Can be + given in one of the following formats: + + **as a vector** -- this is a tuple of pluses, minuses, and zeroes. + + **as three tuples** -- the first tuple is the positives, the second + the negatives and the third the zeroes. + + **as a dict** -- the dictionary should have keys *positives*, + *negatives*, and *zeroes*. + + - ``groundset`` -- (default: ``None``) if not given will construct + the groundset from the parent, or if none is created in the parent, + using the elements found in the data. + - ``positives`` -- (default: ``None``) alternative to ``data``. Should be + a tuple of elements. Requires ``negatives`` to be set. + - ``negatives`` -- (default: ``None``) alternative to ``data``. Should be + a tuple of elements. Requires ``positives`` to be set. + - ``zeroes`` -- (default: ``None``) alternative to ``data``. Should be a + tuple of elements. Requires ``positives`` and ``negatives`` to be set. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: from oriented_matroids.abstract_oriented_matroid import SignedSubsetElement + sage: M = OrientedMatroid([[1],[-1]],key='circuit'); + sage: SignedSubsetElement(M,data = (0,)) + +: + -: + 0: 0 + sage: SignedSubsetElement(M,data = (1,)) + +: 0 + -: + 0: + sage: M = OrientedMatroid([[1],[-1]],key='circuit', groundset=['e']) + sage: SignedSubsetElement(M,data = (1,)) + +: e + -: + 0: + + Elements are also lazy loaded to return the sign of elements from the + groundset:: + + sage: M = OrientedMatroid([[1],[-1]],key='circuit', groundset=['e']) + sage: C = M.elements(); C[0] + +: e + -: + 0: + sage: C[0]('e') + 1 + + .. SEEALSO:: + + - :class:`oriented_matroids.oriented_Matroid.OrientedMatroid` + - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` + + """ + + def __init__(self, parent=None, data=None, groundset=None, + positives=None, negatives=None, zeroes=None): + """ + Initialize ``self``. + """ + # If our groundset isn't set but our parent has one, use its groundset + if groundset is None: + try: + groundset = parent.groundset() + except AttributeError: + groundset = None + + # remove parent if data not present + if parent is None \ + or (data is None and groundset is None and positives is None): + from sage.structure.parent import Parent + data = parent + parent = Parent() + + # instantiate! + self._p = set([]) + self._n = set([]) + self._z = set([]) + + # If we're setting things one item at a time + if positives is not None: + if negatives is None: + raise ValueError( + "If positives is set, negatives must be as well") + + self._p = set(positives) + self._n = set(negatives) + if zeroes is None: + if groundset is None: + self._z = set([]) + else: + gs = set(groundset) + self._z = gs.difference(self._p).difference(self._n) + else: + self._z = set(zeroes) + + # If we already have a signed subset element, use it's data + elif isinstance(data, SignedSubsetElement): + self._p = data.positives() + self._n = data.negatives() + self._z = data.zeroes() + + # If we have a tuple, use its information + elif isinstance(data, tuple): + # if we're given vector format + if data[0] in [-1, 0, 1, '+', '0', '-', '']: + if groundset is not None and len(data) != len(groundset): + raise ValueError( + "Length of vector must be same number of elements as ground set") + for i, j in enumerate(data): + label = i + if groundset is not None: + label = groundset[i] + if j == -1 or j == '-': + self._n.add(label) + elif j == 1 or j == '+': + self._p.add(label) + elif j == 0 or j == '' or j == '0': + self._z.add(label) + else: + raise ValueError("Must be tuple of -1, 0, 1") + + # If we have a tuple of tuples + else: + self._p = set(data[0]) + self._n = set(data[1]) + if len(data) > 2: + self._z = set(data[2]) + elif groundset is not None: + self._z = set(groundset).difference( + self._p).difference(self._n) + # If we have a dictionary, use the keys to figure it out + elif isinstance(data, dict): + if 'p' in data: + self._p = data['p'] + if 'positives' in data: + self._p = data['positives'] + if 'n' in data: + self._n = data['n'] + if 'negatives' in data: + self._n = data['negatives'] + if 'z' in data: + self._z = data['z'] + if 'zeroes' in data: + self._z = data['zeroes'] + else: + raise ValueError( + "Either positives and negatives are set or data is a tuple, OrientedMatroidELement or a dict") + + # Type fix + self._p = set(self._p) + self._n = set(self._n) + self._z = set(self._z) + + # Setup the ground set if it's not set yet + if groundset is None: + self._g = list(self._p.union(self._n).union(self._z)) + else: + if not self.support().union(self.zeroes()).issubset(groundset): + raise ValueError("Elements must appear in groundset") + + # Update the zeroes with everything in the ground set + if self._z is None: + self._z = set(groundset).difference(self.support()) + + # ground set should be everything + if not set(groundset).issubset(self.support().union(self.zeroes())): + raise ValueError( + "Every element must be either positive, negative or zero") + self._g = groundset + + self._g = list(self._g) + + Element.__init__(self, parent) + + def __call__(self, var): + """ + Return the sign of an element in the groundset. + """ + + if var in self.positives(): + return 1 + if var in self.negatives(): + return -1 + if var in self.zeroes(): + return 0 + raise ValueError("Not in groundset") + + def __hash__(self): + """ + Return hashed string of signed subset. + """ + fsp = frozenset(self._p) + fsn = frozenset(self._n) + fsz = frozenset(self._z) + return hash((fsp, fsn, fsz)) + + def __neg__(self): + """ + Return the opposite signed subset. + """ + N = copy.copy(self) + N._p = self._n + N._n = self._p + return N + + def __eq__(self, other): + """ + Return whether two elements are equal. + """ + if isinstance(other, SignedSubsetElement): + if self._p == other._p \ + and self._n == other._n \ + and self._z == other._z: + return True + return False + + def __ne__(self, other): + """ + Return whether two elements are not equal. + """ + return not (self == other) + + def _cmp_(self, other): + """ + Arbitrary comparison function so posets work. + """ + if not isinstance(other, SignedSubsetElement): + return 0 + return 1 + # x = len(self.support()) - len(other.support()) + # if x == 0: + # return x + # return x / abs(x) * -1 + + def __bool__(self): + r""" + Returns whether an element is not considered a zero. + + For an oriented matroid, we consider the empty set + `\emptyset = (\emptyset,\emptyset)` to be a zero as + it is the same as the all zero vector. + """ + if len(self.support()) > 0: + return True + return False + + def __iter__(self): + """ + Returns an iter version of self. + """ + for e in self.groundset(): + yield self(e) + + def _repr_(self): + """ + Return a string of the signed subset. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: from oriented_matroids.abstract_oriented_matroid import SignedSubsetElement + sage: C = [ ((1,4),(2,3)) , ((2,3),(1,4)) ] + sage: M = OrientedMatroid(C,key='circuit') + sage: SignedSubsetElement(M,data = ((1,4),(2,3))) + +: 1,4 + -: 2,3 + 0: + + """ + + if AbstractOrientedMatroid.options.display == 'set': + p = map(str, self.positives()) + n = map(str, self.negatives()) + z = map(str, self.zeroes()) + return "+: " + ','.join(p) + "\n" + \ + "-: " + ','.join(n) + "\n" +\ + "0: " + ','.join(z) + if AbstractOrientedMatroid.options.display == 'vector': + return "(" + ','.join([str(self(e)) for e in self.groundset()]) + ")" + + + def _latex_(self): + r""" + Return a latex representation of the signed subset. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: from oriented_matroids.abstract_oriented_matroid import SignedSubsetElement + sage: C = [ ((1,4),(2,3)) , ((2,3),(1,4)) ] + sage: M = OrientedMatroid(C,key='circuit') + sage: latex(SignedSubsetElement(M,data = ((1,4),(2,3)))) + \left( \left{1,4\right},\left{2,3\right} \right) + + """ + if AbstractOrientedMatroid.options.display == 'set': + p = map(str, self.positives()) + n = map(str, self.negatives()) + return "\\left( \\left{" + ','.join(p) + \ + "\\right},\\left{" + ','.join(n) + "\\right} \\right)" + if AbstractOrientedMatroid.options.display == 'vector': + ground_set = [str(self(e)) for e in self.groundset()] + return "\\left(" + ','.join(ground_set) + "\\right)" + + def __copy__(self): + """ + Return a copy of the element + """ + return SignedSubsetElement(parent=self.parent(), groundset=self.groundset(), positives=self.positives(), negatives=self.negatives(), zeroes=self.zeroes()) + + def __deepcopy__(self): + """ + Return a copy of the element + """ + return SignedSubsetElement(parent=self.parent(), groundset=self.groundset(), positives=self.positives(), negatives=self.negatives(), zeroes=self.zeroes()) + + def to_list(self): + """ + Convert objcet to a list + """ + return eval("[" + ','.join([str(self(e)) for e in self.groundset()]) + "]") + + def positives(self): + """ + Return the set of positives. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: M = OrientedMatroid([[1,-1,1],[-1,1,-1]], key='circuit') + sage: E = M.elements()[0] + sage: E.positives() + {0, 2} + + """ + return self._p + + def negatives(self): + """ + Return the set of negatives. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: M = OrientedMatroid([[1,-1,1],[-1,1,-1]], key='circuit') + sage: E = M.elements()[0] + sage: E.negatives() + {1} + + """ + return self._n + + def zeroes(self): + r""" + Return the set of zeroes. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') + sage: E = M.elements()[0] + sage: E.zeroes() + {2} + + """ + return self._z + + def support(self): + r""" + Return the support set. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') + sage: E = M.elements()[0] + sage: E.support() + {0, 1} + + """ + return self._p.union(self._n) + + def groundset(self): + r""" + Return the ground set. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') + sage: E = M.elements()[0] + sage: E.groundset() + [0, 1, 2] + + """ + return self._g + + def composition(self, other): + r""" + Return the composition of two elements. + + The composition of two elements `X` and `Y`, + denoted `X \circ Y` is given componentwise + where for `e \in E` we have `(X \circ Y)(e) = X(e)` + if `X(e) \neq 0` else it equals `Y(e)`. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids import AbstractOrientedMatroid + sage: AbstractOrientedMatroid.options.display='vector' + sage: M = OrientedMatroid([[0],[1],[-1]], key='vector') + sage: E1 = M.elements()[0]; E2 = M.elements()[1] + sage: E1.composition(E2) + (1) + sage: E2.composition(E1) + (1) + sage: E1.composition(E2) == E2.composition(E1) + True + + """ + p = [] + n = [] + z = [] + for e in self.groundset(): + x = self(e) + # If x is non-zero, keep its value + if x == 1: + p.append(e) + elif x == -1: + n.append(e) + else: + # else grab the value of the other + x = other(e) + if x == 1: + p.append(e) + elif x == -1: + n.append(e) + else: + z.append(e) + return type(self)(self.parent(), positives=p, negatives=n, zeroes=z) + + def separation_set(self, other): + r""" + Return the separation set between two elements. + + The separation set of two elements `X` and `Y` + is given by `S(X,Y) = \left\{e \mid X(e) = -Y(e) \neq 0 \right\}` + """ + return self.positives().intersection(other.negatives()).union(self.negatives().intersection(other.positives())) + + def reorientation(self, change_set): + r""" + Return the reorientation by a set. + + The reorientation of `X` by some `A \subseteq E` is + the signed subset (covector) given by `{}_{-A}X` where + `{}_{-A}X^+ = (X^+ \backslash A) \cup (X^- \cap A)` and similarly for + `{}_{-A}X^-`. + """ + if change_set in self.groundset(): + change_set = set([change_set]) + else: + change_set = set(change_set) + + # ensure every elt is in the groundset + for i in change_set: + if i not in self.groundset(): + raise ValueError("{} is not in the ground set".format(i)) + + p = self.positives().difference(change_set).union( + self.negatives().intersection(change_set)) + n = self.negatives().difference(change_set).union( + self.positives().intersection(change_set)) + return type(self)(self.parent(), positives=p, negatives=n, groundset=self.groundset()) + + def is_conformal_with(self, other): + r""" + Return if the two elements are conformal. + + Two elements `X` and `Y` are *conformal* if + `S(X,Y) = \emptyset`. This is true if and only if `X^+ \subseteq Y^+` + and `X^- \subseteq Y^-`. + """ + return len(self.separation_set(other)) == 0 + + def is_restriction_of(self, other): + r""" + Return if `self` is a restriction of `other`. + + A signed subset `X` is a *restriction* of a signed subset `Y` if + `X^+ \subsetex Y^+` and `X^- \subseteq Y^-`. If `X` is a restriction of + `Y` we sometimes say `X` conforms to `Y`. This should not be mistaken + with *is conformal with*. + """ + return self.positives().issubset(other.positives()) \ + and self.negatives().issubset(other.negatives()) + + def is_tope(self): + r""" + Return whether object is a tope. + + A covector is a tope if it is a maximal + element in the face poset. + + .. WARNING:: + + Requires the method `face_lattice` to exist in the oriented + matroid. + """ + if getattr(self.parent(), 'face_lattice', None) is not None: + raise TypeError( + "Topes are only implemented if .face_lattice() is implemented") + + return self in self.parent().topes() + + def is_simplicial(self): + r""" + Return whether or not a tope is simplicial. + + A tope `T` is simplicial if the interval `[0,T]` is boolean + in the face lattice. We note that the breadth of a lattice + can characterize this. In particular a lattice of breadth `n` + contains a sublattice isomorphic to the Boolean lattice of `2^n` + elements. In other words, if `[0,T]` has `2^n` elements and + the breadth of `[0,T]` is `n` then the interval is boolean + and thus `T` is simplicial. + """ + if not self.is_tope(): + raise TypeError("Only topes can be simplicial") + + P = self.parent().face_lattice() + I = P.interval(P.bottom(), self) + PP = P.sublattice(I) + b = PP.breadth() + if len(I) == 2**b: + return True + return False + + def is_zero(self): + """ + Return whether or not element is 0 + """ + return len([1 for e in self.groundset() if self(e) != 0]) == 0 + class AbstractOrientedMatroid(UniqueRepresentation, Parent): r""" The category of oriented matroids. @@ -40,22 +620,9 @@ class AbstractOrientedMatroid(UniqueRepresentation, Parent): See :wikipedia:`Oriented_matroid` for details. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroids - sage: M = OrientedMatroids(); M - Category of oriented matroids - sage: M.super_categories() - [Category of sets] - .. SEEALSO:: :class:`oriented_matroids.oriented_matroid.OrientedMatroid` - - TESTS:: - - sage: TestSuite(M).run() """ """ @@ -65,6 +632,26 @@ class AbstractOrientedMatroid(UniqueRepresentation, Parent): Element = SignedSubsetElement + class options(GlobalOptions): + r""" + xxx + + @OPTIONS@ + + .. NOTE:: + + Changing the ``convention`` for tableaux also changes the + ``convention`` for partitions. + + """ + NAME = 'OrientedMatroids' + display = dict(default="set", + description='Changes how signed subsets are displayed.', + values=dict(set='display as sets', + vector='display as vectors', + ), + ) + def __init__(self, category=None): if category is None: category = Sets() @@ -473,3 +1060,5 @@ def _element_constructor_(self, x): return False except ValueError: return False + + diff --git a/oriented_matroids/all.py b/oriented_matroids/all.py index c14aa58..c7e39d1 100644 --- a/oriented_matroids/all.py +++ b/oriented_matroids/all.py @@ -1,6 +1,6 @@ from __future__ import absolute_import from oriented_matroid import OrientedMatroid -from oriented_matroids_category import OrientedMatroids +from abstract_oriented_matroid import AbstractOrientedMatroid # from sage.misc.lazy_import import lazy_import # lazy_import('sage.matroids.oriented_matroids', diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index b911b9f..149329a 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -20,7 +20,6 @@ ############################################################################## from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid -from oriented_matroids.signed_subset_element import SignedSubsetElement from sage.categories.sets_cat import Sets diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 111c8b0..9868486 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -20,7 +20,6 @@ ############################################################################## from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid -from oriented_matroids.signed_vector_element import SignedVectorElement from sage.categories.sets_cat import Sets import copy diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 000112c..7dd262a 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -86,6 +86,7 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): EXAMPLES:: sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids import AbstractOrientedMatroid sage: A = hyperplane_arrangements.braid(3) sage: M = OrientedMatroid(A); M @@ -94,6 +95,7 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): (Hyperplane 0*t0 + t1 - t2 + 0, Hyperplane t0 - t1 + 0*t2 + 0, Hyperplane t0 + 0*t1 - t2 + 0) + sage: AbstractOrientedMatroid.options.display='vector' sage: M.elements() [(0,0,0), (0,1,1), diff --git a/oriented_matroids/signed_subset_element.py b/oriented_matroids/signed_subset_element.py deleted file mode 100644 index d220fd8..0000000 --- a/oriented_matroids/signed_subset_element.py +++ /dev/null @@ -1,569 +0,0 @@ -r""" -Signed Subset element ---------------------------------------- - -This implements a basic signed subet element which is used for oriented -matroids. - -AUTHORS: - -- Aram Dermenjian (2019-07-12): Initial version -""" - -############################################################################## -# Copyright (C) 2019 Aram Dermenjian -# -# Distributed under the terms of the GNU General Public License (GPL) -# -# The full text of the GPL is available at: -# -# http://www.gnu.org/licenses/ -############################################################################## -from sage.structure.element import Element - -import copy - - -class SignedSubsetElement(Element): - r""" - Creates a signed subset. - - INPUT: - - - ``parent`` -- the parent object of the element. Usually is a class - generated by :class:`OrientedMatroid`. - - ``data`` -- (default: ``None``) is a tuple with information. Can be - given in one of the following formats: - + **as a vector** -- this is a tuple of pluses, minuses, and zeroes. - + **as three tuples** -- the first tuple is the positives, the second - the negatives and the third the zeroes. - + **as a dict** -- the dictionary should have keys *positives*, - *negatives*, and *zeroes*. - - - ``groundset`` -- (default: ``None``) if not given will construct - the groundset from the parent, or if none is created in the parent, - using the elements found in the data. - - ``positives`` -- (default: ``None``) alternative to ``data``. Should be - a tuple of elements. Requires ``negatives`` to be set. - - ``negatives`` -- (default: ``None``) alternative to ``data``. Should be - a tuple of elements. Requires ``positives`` to be set. - - ``zeroes`` -- (default: ``None``) alternative to ``data``. Should be a - tuple of elements. Requires ``positives`` and ``negatives`` to be set. - - EXAMPLES:: - - sage: from oriented_matroids.oriented_matroid import OrientedMatroid - sage: from oriented_matroids.signed_subset_element import SignedSubsetElement - sage: M = OrientedMatroid([[1],[-1]],key='circuit'); - sage: SignedSubsetElement(M,data = (0,)) - +: - -: - 0: 0 - sage: SignedSubsetElement(M,data = (1,)) - +: 0 - -: - 0: - sage: M = OrientedMatroid([[1],[-1]],key='circuit', groundset=['e']) - sage: SignedSubsetElement(M,data = (1,)) - +: e - -: - 0: - - Elements are also lazy loaded to return the sign of elements from the - groundset:: - - sage: M = OrientedMatroid([[1],[-1]],key='circuit', groundset=['e']) - sage: C = M.elements(); C[0] - +: e - -: - 0: - sage: C[0]('e') - 1 - - .. SEEALSO:: - - - :class:`oriented_matroids.oriented_Matroid.OrientedMatroid` - - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` - - """ - - def __init__(self, parent=None, data=None, groundset=None, - positives=None, negatives=None, zeroes=None): - """ - Initialize ``self``. - """ - # If our groundset isn't set but our parent has one, use its groundset - if groundset is None: - try: - groundset = parent.groundset() - except AttributeError: - groundset = None - - # remove parent if data not present - if parent is None \ - or (data is None and groundset is None and positives is None): - from sage.structure.parent import Parent - data = parent - parent = Parent() - - # instantiate! - self._p = set([]) - self._n = set([]) - self._z = set([]) - - # If we're setting things one item at a time - if positives is not None: - if negatives is None: - raise ValueError( - "If positives is set, negatives must be as well") - - self._p = set(positives) - self._n = set(negatives) - if zeroes is None: - if groundset is None: - self._z = set([]) - else: - gs = set(groundset) - self._z = gs.difference(self._p).difference(self._n) - else: - self._z = set(zeroes) - - # If we already have a signed subset element, use it's data - elif isinstance(data, SignedSubsetElement): - self._p = data.positives() - self._n = data.negatives() - self._z = data.zeroes() - - # If we have a tuple, use its information - elif isinstance(data, tuple): - # if we're given vector format - if data[0] in [-1, 0, 1, '+', '0', '-', '']: - if groundset is not None and len(data) != len(groundset): - raise ValueError( - "Length of vector must be same number of elements as ground set") - for i, j in enumerate(data): - label = i - if groundset is not None: - label = groundset[i] - if j == -1 or j == '-': - self._n.add(label) - elif j == 1 or j == '+': - self._p.add(label) - elif j == 0 or j == '' or j == '0': - self._z.add(label) - else: - raise ValueError("Must be tuple of -1, 0, 1") - - # If we have a tuple of tuples - else: - self._p = set(data[0]) - self._n = set(data[1]) - if len(data) > 2: - self._z = set(data[2]) - elif groundset is not None: - self._z = set(groundset).difference( - self._p).difference(self._n) - # If we have a dictionary, use the keys to figure it out - elif isinstance(data, dict): - if 'p' in data: - self._p = data['p'] - if 'positives' in data: - self._p = data['positives'] - if 'n' in data: - self._n = data['n'] - if 'negatives' in data: - self._n = data['negatives'] - if 'z' in data: - self._z = data['z'] - if 'zeroes' in data: - self._z = data['zeroes'] - else: - raise ValueError( - "Either positives and negatives are set or data is a tuple, OrientedMatroidELement or a dict") - - # Type fix - self._p = set(self._p) - self._n = set(self._n) - self._z = set(self._z) - - # Setup the ground set if it's not set yet - if groundset is None: - self._g = list(self._p.union(self._n).union(self._z)) - else: - if not self.support().union(self.zeroes()).issubset(groundset): - raise ValueError("Elements must appear in groundset") - - # Update the zeroes with everything in the ground set - if self._z is None: - self._z = set(groundset).difference(self.support()) - - # ground set should be everything - if not set(groundset).issubset(self.support().union(self.zeroes())): - raise ValueError( - "Every element must be either positive, negative or zero") - self._g = groundset - - self._g = list(self._g) - - Element.__init__(self, parent) - - def __call__(self, var): - """ - Return the sign of an element in the groundset. - """ - - if var in self.positives(): - return 1 - if var in self.negatives(): - return -1 - if var in self.zeroes(): - return 0 - raise ValueError("Not in groundset") - - def __hash__(self): - """ - Return hashed string of signed subset. - """ - fsp = frozenset(self._p) - fsn = frozenset(self._n) - fsz = frozenset(self._z) - return hash((fsp, fsn, fsz)) - - def __neg__(self): - """ - Return the opposite signed subset. - """ - N = copy.copy(self) - N._p = self._n - N._n = self._p - return N - - def __eq__(self, other): - """ - Return whether two elements are equal. - """ - if isinstance(other, SignedSubsetElement): - if self._p == other._p \ - and self._n == other._n \ - and self._z == other._z: - return True - return False - - def __ne__(self, other): - """ - Return whether two elements are not equal. - """ - return not (self == other) - - def _cmp_(self, other): - """ - Arbitrary comparison function so posets work. - """ - if not isinstance(other, SignedSubsetElement): - return 0 - return 1 - # x = len(self.support()) - len(other.support()) - # if x == 0: - # return x - # return x / abs(x) * -1 - - def __bool__(self): - r""" - Returns whether an element is not considered a zero. - - For an oriented matroid, we consider the empty set - `\emptyset = (\emptyset,\emptyset)` to be a zero as - it is the same as the all zero vector. - """ - if len(self.support()) > 0: - return True - return False - - def __iter__(self): - """ - Returns an iter version of self. - """ - for e in self.groundset(): - yield self(e) - - def _repr_(self): - """ - Return a string of the signed subset. - - EXAMPLES:: - - sage: from oriented_matroids.oriented_matroid import OrientedMatroid - sage: from oriented_matroids.signed_subset_element import SignedSubsetElement - sage: C = [ ((1,4),(2,3)) , ((2,3),(1,4)) ] - sage: M = OrientedMatroid(C,key='circuit') - sage: SignedSubsetElement(M,data = ((1,4),(2,3))) - +: 1,4 - -: 2,3 - 0: - - """ - - p = map(str, self.positives()) - n = map(str, self.negatives()) - z = map(str, self.zeroes()) - return "+: " + ','.join(p) + "\n" + \ - "-: " + ','.join(n) + "\n" +\ - "0: " + ','.join(z) - - def _latex_(self): - r""" - Return a latex representation of the signed subset. - - EXAMPLES:: - - sage: from oriented_matroids.oriented_matroid import OrientedMatroid - sage: from oriented_matroids.signed_subset_element import SignedSubsetElement - sage: C = [ ((1,4),(2,3)) , ((2,3),(1,4)) ] - sage: M = OrientedMatroid(C,key='circuit') - sage: latex(SignedSubsetElement(M,data = ((1,4),(2,3)))) - \left( \left{1,4\right},\left{2,3\right} \right) - - """ - p = map(str, self.positives()) - n = map(str, self.negatives()) - return "\\left( \\left{" + ','.join(p) + \ - "\\right},\\left{" + ','.join(n) + "\\right} \\right)" - - def __copy__(self): - """ - Return a copy of the element - """ - return SignedSubsetElement(parent=self.parent(), groundset=self.groundset(), positives=self.positives(), negatives=self.negatives(), zeroes=self.zeroes()) - - def __deepcopy__(self): - """ - Return a copy of the element - """ - return SignedSubsetElement(parent=self.parent(), groundset=self.groundset(), positives=self.positives(), negatives=self.negatives(), zeroes=self.zeroes()) - - def to_list(self): - """ - Convert objcet to a list - """ - return eval("[" + ','.join([str(self(e)) for e in self.groundset()]) + "]") - - def positives(self): - """ - Return the set of positives. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: M = OrientedMatroid([[1,-1,1],[-1,1,-1]], key='circuit') - sage: E = M.elements()[0] - sage: E.positives() - {0, 2} - - """ - return self._p - - def negatives(self): - """ - Return the set of negatives. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: M = OrientedMatroid([[1,-1,1],[-1,1,-1]], key='circuit') - sage: E = M.elements()[0] - sage: E.negatives() - {1} - - """ - return self._n - - def zeroes(self): - r""" - Return the set of zeroes. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') - sage: E = M.elements()[0] - sage: E.zeroes() - {2} - - """ - return self._z - - def support(self): - r""" - Return the support set. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') - sage: E = M.elements()[0] - sage: E.support() - {0, 1} - - """ - return self._p.union(self._n) - - def groundset(self): - r""" - Return the ground set. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') - sage: E = M.elements()[0] - sage: E.groundset() - [0, 1, 2] - - """ - return self._g - - def composition(self, other): - r""" - Return the composition of two elements. - - The composition of two elements `X` and `Y`, - denoted `X \circ Y` is given componentwise - where for `e \in E` we have `(X \circ Y)(e) = X(e)` - if `X(e) \neq 0` else it equals `Y(e)`. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: M = OrientedMatroid([[0],[1],[-1]], key='vector') - sage: E1 = M.elements()[0]; E2 = M.elements()[1] - sage: E1.composition(E2) - (1) - sage: E2.composition(E1) - (1) - sage: E1.composition(E2) == E2.composition(E1) - True - - """ - p = [] - n = [] - z = [] - for e in self.groundset(): - x = self(e) - # If x is non-zero, keep its value - if x == 1: - p.append(e) - elif x == -1: - n.append(e) - else: - # else grab the value of the other - x = other(e) - if x == 1: - p.append(e) - elif x == -1: - n.append(e) - else: - z.append(e) - return type(self)(self.parent(), positives=p, negatives=n, zeroes=z) - - def separation_set(self, other): - r""" - Return the separation set between two elements. - - The separation set of two elements `X` and `Y` - is given by `S(X,Y) = \left\{e \mid X(e) = -Y(e) \neq 0 \right\}` - """ - return self.positives().intersection(other.negatives()).union(self.negatives().intersection(other.positives())) - - def reorientation(self, change_set): - r""" - Return the reorientation by a set. - - The reorientation of `X` by some `A \subseteq E` is - the signed subset (covector) given by `{}_{-A}X` where - `{}_{-A}X^+ = (X^+ \backslash A) \cup (X^- \cap A)` and similarly for - `{}_{-A}X^-`. - """ - if change_set in self.groundset(): - change_set = set([change_set]) - else: - change_set = set(change_set) - - # ensure every elt is in the groundset - for i in change_set: - if i not in self.groundset(): - raise ValueError("{} is not in the ground set".format(i)) - - p = self.positives().difference(change_set).union( - self.negatives().intersection(change_set)) - n = self.negatives().difference(change_set).union( - self.positives().intersection(change_set)) - return type(self)(self.parent(), positives=p, negatives=n, groundset=self.groundset()) - - def is_conformal_with(self, other): - r""" - Return if the two elements are conformal. - - Two elements `X` and `Y` are *conformal* if - `S(X,Y) = \emptyset`. This is true if and only if `X^+ \subseteq Y^+` - and `X^- \subseteq Y^-`. - """ - return len(self.separation_set(other)) == 0 - - def is_restriction_of(self, other): - r""" - Return if `self` is a restriction of `other`. - - A signed subset `X` is a *restriction* of a signed subset `Y` if - `X^+ \subsetex Y^+` and `X^- \subseteq Y^-`. If `X` is a restriction of - `Y` we sometimes say `X` conforms to `Y`. This should not be mistaken - with *is conformal with*. - """ - return self.positives().issubset(other.positives()) \ - and self.negatives().issubset(other.negatives()) - - def is_tope(self): - r""" - Return whether object is a tope. - - A covector is a tope if it is a maximal - element in the face poset. - - .. WARNING:: - - Requires the method `face_lattice` to exist in the oriented - matroid. - """ - if getattr(self.parent(), 'face_lattice', None) is not None: - raise TypeError( - "Topes are only implemented if .face_lattice() is implemented") - - return self in self.parent().topes() - - def is_simplicial(self): - r""" - Return whether or not a tope is simplicial. - - A tope `T` is simplicial if the interval `[0,T]` is boolean - in the face lattice. We note that the breadth of a lattice - can characterize this. In particular a lattice of breadth `n` - contains a sublattice isomorphic to the Boolean lattice of `2^n` - elements. In other words, if `[0,T]` has `2^n` elements and - the breadth of `[0,T]` is `n` then the interval is boolean - and thus `T` is simplicial. - """ - if not self.is_tope(): - raise TypeError("Only topes can be simplicial") - - P = self.parent().face_lattice() - I = P.interval(P.bottom(), self) - PP = P.sublattice(I) - b = PP.breadth() - if len(I) == 2**b: - return True - return False - - def is_zero(self): - """ - Return whether or not element is 0 - """ - return len([1 for e in self.groundset() if self(e) != 0]) == 0 diff --git a/oriented_matroids/signed_vector_element.py b/oriented_matroids/signed_vector_element.py deleted file mode 100644 index 6087185..0000000 --- a/oriented_matroids/signed_vector_element.py +++ /dev/null @@ -1,121 +0,0 @@ -r""" -Signed vector element for vector based oriented matroids. - ---------------------------------------- - -This implements an oriented matroid element. Depending on the implementation -this can either be seen as a signed vector or covector. - -AUTHORS: - -- Aram Dermenjian (2019-07-12): Initial version -""" - -############################################################################## -# Copyright (C) 2019 Aram Dermenjian -# -# Distributed under the terms of the GNU General Public License (GPL) -# -# The full text of the GPL is available at: -# -# http://www.gnu.org/licenses/ -############################################################################## -from oriented_matroids.signed_subset_element import SignedSubsetElement - - -class SignedVectorElement(SignedSubsetElement): - r""" - Creates an oriented matroid element. - - INPUT: - - - ``parent`` -- the parent object of the element. Usually is a class - generated by :class:`OrientedMatroid`. - - ``data`` -- (default: ``None``) is a tuple with information. Can be - given in one of the following formats: - + **as a vector** -- this is a tuple of pluses, minuses, and zeroes. - + **as three tuples** -- the first tuple is the positives, the second - the negatives and the third the zeroes. - + **as a dict** -- the dictionary should have keys *positives*, - *negatives*, and *zeroes*. - - - ``groundset`` -- (default: ``None``) if not given will construct - the groundset from the parent, or if none is created in the parent, - using the elements found in the data. - - ``positives`` -- (default: ``None``) alternative to ``data``. Should be - a tuple of elements. Requires ``negatives`` to be set. - - ``negatives`` -- (default: ``None``) alternative to ``data``. Should be - a tuple of elements. Requires ``positives`` to be set. - - ``zeroes`` -- (default: ``None``) alternative to ``data``. Should be a - tuple of elements. Requires ``positives`` and ``negatives`` to be set. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: from oriented_matroids.signed_vector_element import SignedVectorElement - - sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], - ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0],[0,0,0]] - sage: M = OrientedMatroid(C, key='covector') - sage: SignedVectorElement(M,data = (0,-1,1)) - (0,-1,1) - sage: SignedVectorElement(M,data = (1,1,-1)) - (1,1,-1) - sage: M = OrientedMatroid(C, key='covector',groundset=['e','f','g']) - sage: SignedVectorElement(M,data = (1,-1,0)) - (1,-1,0) - - .. SEEALSO:: - - - :class:`oriented_matroids.oriented_matroid.OrientedMatroid` - - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` - - :class:`oriented_matroids.signed_subset_element.SignedSubsetElement` - - """ - - def __init__(self, parent=None, data=None, groundset=None, - positives=None, negatives=None, zeroes=None): - """ - Initialize ``self``. - """ - - SignedSubsetElement.__init__( - self, parent, data, groundset, positives, negatives, zeroes) - - def _repr_(self): - """ - Return a representation depending on implementation. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: from oriented_matroids.signed_vector_element import SignedVectorElement - - sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], - ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], - ....: [0,0,0]] - sage: M = OrientedMatroid(C, key='covector') - sage: SignedVectorElement(M,data = (1,1,-1)) - (1,1,-1) - - """ - return "(" + ','.join([str(self(e)) for e in self.groundset()]) + ")" - - def _latex_(self): - r""" - Return a latex representation depending on implementation. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: from oriented_matroids.signed_vector_element import SignedVectorElement - sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], - ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], - ....: [0,0,0]] - sage: M = OrientedMatroid(C, key='covector') - sage: latex(SignedVectorElement(M,data = (1,1,-1))) - \left(1,1,-1\right) - - """ - ground_set = [str(self(e)) for e in self.groundset()] - return "\\left(" + ','.join(ground_set) + "\\right)" diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index a1c3a0d..5e5f14d 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -20,7 +20,6 @@ ############################################################################## from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid -from oriented_matroids.signed_vector_element import SignedVectorElement from sage.categories.sets_cat import Sets From 49dc9728ed736142d768d735e23e1fa1d9142bf7 Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 18 Jul 2023 14:00:15 +0100 Subject: [PATCH 084/101] Removing mentioning of category file --- oriented_matroids/abstract_oriented_matroid.py | 5 +---- oriented_matroids/oriented_matroid.py | 4 ++-- .../real_hyperplane_arrangement_oriented_matroid.py | 4 ++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py index 698e247..df5b895 100644 --- a/oriented_matroids/abstract_oriented_matroid.py +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -332,7 +332,6 @@ def _repr_(self): if AbstractOrientedMatroid.options.display == 'vector': return "(" + ','.join([str(self(e)) for e in self.groundset()]) + ")" - def _latex_(self): r""" Return a latex representation of the signed subset. @@ -1059,6 +1058,4 @@ def _element_constructor_(self, x): return x return False except ValueError: - return False - - + return False \ No newline at end of file diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 7dd262a..6b7986d 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -40,7 +40,7 @@ import PointConfiguration from sage.graphs.digraph import DiGraph from sage.structure.element import Matrix -from oriented_matroids.oriented_matroids_category import OrientedMatroids +from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid import copy @@ -209,7 +209,7 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): 'Matrices are currently only implemented using chirotope axioms') key = 'chirotope' - if key not in OrientedMatroids.keys: + if key not in AbstractOrientedMatroid.keys: raise ValueError("invalid type key") # In the following cases, deep_tupler is used since we are using diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index a682157..230c827 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -21,7 +21,7 @@ from oriented_matroids.covector_oriented_matroid import CovectorOrientedMatroid -from oriented_matroids.oriented_matroids_category import OrientedMatroids +from sage.categories.sets_cat import Sets class RealHyperplaneArrangementOrientedMatroid(CovectorOrientedMatroid): r""" @@ -69,7 +69,7 @@ def __classcall__(cls, data, groundset=None, category=None): Normalize arguments and set class. """ if category is None: - category = OrientedMatroids() + category = Sets() return super(RealHyperplaneArrangementOrientedMatroid, cls) \ .__classcall__(cls, data=data, From ef84ce2821e221d22f36479108d760efb9fbe535 Mon Sep 17 00:00:00 2001 From: lizzy Date: Thu, 20 Jul 2023 14:22:41 +0100 Subject: [PATCH 085/101] Adding extra examples for testing --- .../abstract_oriented_matroid.py | 19 +++++++++++++++++++ oriented_matroids/circuit_oriented_matroid.py | 4 ++++ oriented_matroids/vector_oriented_matroid.py | 11 +++++++++++ 3 files changed, 34 insertions(+) diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py index df5b895..1a6c72c 100644 --- a/oriented_matroids/abstract_oriented_matroid.py +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -754,6 +754,17 @@ def to_covector(self): def dual(self): """ Return the dual oriented matroid. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: A = hyperplane_arrangements.braid(3) + sage: M = OrientedMatroid(A) + sage: m = M.matroid() + sage: m.dual() + Dual of 'Matroid of rank 2 on 3 elements' + sage: m.dual() is m + False """ pass @@ -787,6 +798,14 @@ def rank(self): def an_element(self): """ Returns an arbitrary element. + + EXAMPLES:: + + sage: D = DiGraph({'v1':{'v2':1,'v3':2,'v4':3},'v2':{'v3':4,'v4':5},'v3':{'v4':6}}) + sage: M = OrientedMatroid(D,key="circuit") + sage: M.an_element() in M.circuits() + True + """ from sage.misc.prandom import randint els = self.elements() diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 149329a..819e930 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -61,6 +61,10 @@ class CircuitOrientedMatroid(AbstractOrientedMatroid): Circuit oriented matroid of rank 3 sage: M.groundset() (1, 2, 3, 4) + sage: M.an_element() in M.elements() + True + sage: M.elements() == M.circuits() + True .. SEEALSO:: diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index 5e5f14d..498a504 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -226,6 +226,17 @@ def circuits(self): Given a vector oriented matroid, the set of circuits is the set `Min(V)` which denotes the set of inclusion-minimal (nonempty) signed subsets. + + EXAMPLES:: + sage: from oriented_matroids import OrientedMatroid + sage: OrientedMatroid([[1],[-1],[0]], key='vector') + sage: M.circuits() + [+: 0 + -: + 0: , + +: + -: 0 + 0: ] """ from sage.combinat.posets.posets import Poset from oriented_matroids import OrientedMatroid From 4260f0b9ee0caae1815b87022d5ef19a448eba21 Mon Sep 17 00:00:00 2001 From: lizzy Date: Thu, 20 Jul 2023 16:15:17 +0100 Subject: [PATCH 086/101] Fixing changes --- oriented_matroids/covector_oriented_matroid.py | 3 --- .../real_hyperplane_arrangement_oriented_matroid.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 7808623..9868486 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -92,11 +92,8 @@ def __init__(self, data, groundset=None, category=None): """ Initialize ``self`` """ -<<<<<<< HEAD AbstractOrientedMatroid.__init__(self, category=category) -======= ->>>>>>> d271389a078e0b61990997f208ea4542addc2955 # Set up our covectors covectors = [] for d in data: diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index d8deda3..230c827 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -39,7 +39,7 @@ class RealHyperplaneArrangementOrientedMatroid(CovectorOrientedMatroid): EXAMPLES:: - sage: from oriented_matroids.constructor import OrientedMatroid + sage: from oriented_matroids import OrientedMatroid sage: A = hyperplane_arrangements.braid(3) sage: M = OrientedMatroid(A); M Hyperplane arrangement oriented matroid of rank 2 From 12a0e17ecef40e1c0658d649a25c3a7b370ab065 Mon Sep 17 00:00:00 2001 From: lizzy Date: Fri, 21 Jul 2023 15:29:53 +0100 Subject: [PATCH 087/101] Adding examples and fixing indentation --- .../abstract_oriented_matroid.py | 12 + oriented_matroids/oriented_matroid.py | 266 +----------------- oriented_matroids/vector_oriented_matroid.py | 8 +- 3 files changed, 17 insertions(+), 269 deletions(-) diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py index 1a6c72c..4f62ec3 100644 --- a/oriented_matroids/abstract_oriented_matroid.py +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -694,6 +694,18 @@ def elements(self): def circuits(self): """ Return all circuits. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatriod + sage: M = OrientedMatroid([[1],[-1]],key='circuit') + sage: M.circuits() + [+: 0 + -: + 0: , + +: + -: 0 + 0: ] """ if "_circuits" in dir(self): return self._circuits diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index ddd29df..919a06a 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD:oriented_matroids/oriented_matroid.py # -*- coding: utf-8 -*- r""" Oriented matroids construction @@ -262,267 +261,4 @@ def deep_tupler(obj): """ if isinstance(obj, list) or isinstance(obj, set): return tuple([deep_tupler(i) for i in obj]) - return obj -======= -# -*- coding: utf-8 -*- -r""" -Oriented matroids construction - -Theory -====== - -Oriented matroids are ... - -Built-in oriented matroids -========================== - -... - -Constructing oriented matroids -============================== - -To define your own oriented matroid,... - - -AUTHORS: - -- Aram Dermenjian (2019-07-12): initial version - -""" - -# ***************************************************************************** -# Copyright (C) 2019 Aram Dermenjian -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# http://www.gnu.org/licenses/ -# ***************************************************************************** - -from sage.geometry.hyperplane_arrangement.arrangement \ - import HyperplaneArrangementElement -from sage.geometry.triangulation.point_configuration \ - import PointConfiguration -from sage.graphs.digraph import DiGraph -from sage.structure.element import Matrix -import copy - - -def OrientedMatroid(data=None, groundset=None, key=None, **kwds): - r""" - Construct an oriented matroid. - - The implementation of the oriented matroid differentiates which - axiom set that will be used.# - - INPUT: - - - ``groundset`` -- (default: ``None``) is the ground set that will be - used for the oriented matroid. - - - ``data`` -- (default: ``None``) the data that will be used to define - the oriented matroids. It can be one of the following: - - + Objects - - + Hyperplane Arrangement - + Point Configuration - + Digraph - + Matrix (not yet implemented) - - + A list or tuple of - - + :class:`SignedSubsetElement` - + :class:`SignedVectorElement` - + A tuple with positive, negative, and zero sets. - - - ``key`` -- (default: ``None``) is the representation of the - oriented matroid. It can be one of the following: - - + ``'covector'`` - uses covector axioms with covectors - + ``'vector'`` - uses vector axioms with signed subsets - + ``'circuit'`` - uses circuit axioms with signed subsets - + ``None`` - try and guess key. - - Further options: - - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - - sage: A = hyperplane_arrangements.braid(3) - sage: M = OrientedMatroids(A); M - Hyperplane arrangement oriented matroid of rank 2 - sage: M.groundset() - (Hyperplane 0*t0 + t1 - t2 + 0, - Hyperplane t0 - t1 + 0*t2 + 0, - Hyperplane t0 + 0*t1 - t2 + 0) - sage: M.elements() - [(0,0,0), - (0,1,1), - (0,-1,-1), - (1,0,1), - (1,1,1), - (1,-1,0), - (1,-1,1), - (1,-1,-1), - (-1,0,-1), - (-1,1,0), - (-1,1,1), - (-1,1,-1), - (-1,-1,-1)] - - sage: D = DiGraph({'v1':{'v2':1,'v3':2,'v4':3},'v2':{'v3':4,'v4':5},'v3':{'v4':6}}) - sage: M = OrientedMatroid(D,key="circuit"); M - Circuit oriented matroid of rank 3 - sage: len(M.circuits()) - 14 - - sage: PC = PointConfiguration([[1,0,0],[0,1,0],[0,0,1],[1/2,1/2,0],[0,1/2,1/2],[1/3,1/3,1/3]]) - sage: M = OrientedMatroid(PC); M - Circuit oriented matroid of rank 3 - sage: M.matroid() - Matroid of rank 3 on 6 elements with 16 bases - - sage: OrientedMatroid([[0]],key='covector') - Covector oriented matroid of rank 0 - sage: OrientedMatroid([[0]],key='circuit') - Traceback (most recent call last): - ... - ValueError: Empty set not allowed - - OUTPUT: - - An oriented matroid whose axioms are determined by the type. - - .. TODO:: - - - Currently chirotopes are not implemented - - We need a way to go from one type to another - - .. SEEALSO:: - - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` - - REFERENCES: - - For more information see [BLSWZ1999]_ . - - """ - - # Instantiate oriented matroid - OM = None - - # If we have a hyperplane arrangement we need to force the key to be an - # arrangement, - if isinstance(data, HyperplaneArrangementElement): - if key != 'covector' and key is not None: - raise ValueError( - 'Hyperplane arrangements are currently only implemented using covector axioms') - key = 'real_hyperplane_arrangement' - elif isinstance(data, PointConfiguration): - if key != 'circuit' and key is not None: - raise ValueError( - 'Point configurations are currently only implemented using circuit axioms') - key = 'circuit' - # PC circuits are given as (+, 0, -); and only half are given - ci = [(C[0], C[2], C[1]) for C in data.circuits()] - ci += [(C[2], C[0], C[1]) for C in data.circuits()] - data = ci - elif isinstance(data, DiGraph): - if key != 'circuit' and key is not None: - raise ValueError( - 'Digraphs are currently only implemented using circuit axioms') - key = 'circuit' - - # we need to add negative edges in order to do all simple cycles - digraph = copy.copy(data) - edges = copy.copy(list(digraph.edges())) - groundset = [] - if len(edges) != len(set(edges)): - raise ValueError('Edge labels need to be unique') - if None in digraph.edge_labels(): - raise ValueError('Edge labels must be set for all edges') - - # Add minus edges to properly get cycles - for e in edges: - digraph.add_edge(e[1], e[0], "NEG_"+str(e[2])) - groundset.append(str(e[2])) - # Each cycle defines a circuit - data = [] - for c in digraph.all_cycles_iterator(simple=True): - p = set([]) - n = set([]) - for e in range(len(c) - 1): - e = str(digraph.edge_label(c[e], c[e+1])) - if e.startswith('NEG_'): - n.add(e.strip('NEG_')) - else: - p.add(e) - # If an edge exists in both sets, then this is a false cycle. - # This implies we have ee^-1 which is why it's false. - # So we only add the true ones. - if len(p.intersection(n)) == 0: - data.append([p, n]) - elif isinstance(data, Matrix): - if key != 'chirotope' and key is not None: - raise ValueError( - 'Matrices are currently only implemented using chirotope axioms') - key = 'chirotope' - - #if key not in OrientedMatroid.keys: - #raise ValueError("invalid type key") - - # In the following cases, deep_tupler is used since we are using - # UniqueRepresentation Which doesn't allow us to have non-hashable things. - if key == "covector": - from oriented_matroids.covector_oriented_matroid \ - import CovectorOrientedMatroid - data = deep_tupler(data) - if groundset is not None: - groundset = deep_tupler(groundset) - OM = CovectorOrientedMatroid(data, groundset=groundset) - elif key == "circuit": - from oriented_matroids.circuit_oriented_matroid \ - import CircuitOrientedMatroid - data = deep_tupler(data) - if groundset is not None: - groundset = deep_tupler(groundset) - OM = CircuitOrientedMatroid(data, groundset=groundset) - elif key == "vector": - from oriented_matroids.vector_oriented_matroid \ - import VectorOrientedMatroid - data = deep_tupler(data) - if groundset is not None: - groundset = deep_tupler(groundset) - OM = VectorOrientedMatroid(data, groundset=groundset) - elif key == "real_hyperplane_arrangement": - from oriented_matroids.real_hyperplane_arrangement_oriented_matroid \ - import RealHyperplaneArrangementOrientedMatroid - A = copy.copy(data) - if groundset is None: - groundset = deep_tupler(A.hyperplanes()) - else: - groundset = deep_tupler(groundset) - OM = RealHyperplaneArrangementOrientedMatroid(A, groundset=groundset) - - if OM is None: - raise NotImplementedError( - "Oriented matroid of type {} is not implemented".format(key)) - - if OM.is_valid(): - return OM - - raise ValueError("Oriented matroid is not valid") - - -def deep_tupler(obj): - r""" - changes a (nested) list or set into a (nested) tuple to be hashable - """ - if isinstance(obj, list) or isinstance(obj, set): - return tuple([deep_tupler(i) for i in obj]) - return obj ->>>>>>> d271389a078e0b61990997f208ea4542addc2955:oriented_matroids/constructor.py + return obj \ No newline at end of file diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index 498a504..620231e 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -226,15 +226,15 @@ def circuits(self): Given a vector oriented matroid, the set of circuits is the set `Min(V)` which denotes the set of inclusion-minimal (nonempty) signed subsets. - + EXAMPLES:: sage: from oriented_matroids import OrientedMatroid - sage: OrientedMatroid([[1],[-1],[0]], key='vector') + sage: M = OrientedMatroid([[1],[-1],[0]], key='vector') sage: M.circuits() [+: 0 - -: + -: 0: , - +: + +: -: 0 0: ] """ From 90c0229eab2d72f910b3ac55c9cbd7b2cdbaedb4 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 26 Jul 2023 10:33:38 +0100 Subject: [PATCH 088/101] Creating a change_type function --- .../abstract_oriented_matroid.py | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py index df5b895..8a069c1 100644 --- a/oriented_matroids/abstract_oriented_matroid.py +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -723,33 +723,29 @@ def covectors(self): if "_covectors" in dir(self): return self._covectors raise NotImplementedError("Covectors not implemented") - - def to_circuit(self): - """ - Return circuit oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.circuits(), - key='circuit', - groundset=self.groundset()) - - def to_vector(self): - """ - Return vector oriented matroid. - """ - from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.vectors(), - key='vector', - groundset=self.groundset()) - - def to_covector(self): - """ - Return covector oriented matroid. - """ + + + def change_type(self, new_type=None): + ''' + Returns an oriented matroid of type specified. + ''' from oriented_matroids import OrientedMatroid - return OrientedMatroid(self.covectors(), - key='covector', - groundset=self.groundset()) + if new_type == None: + pass + elif new_type == 'circuit': + return OrientedMatroid(self.circuits(), + key='circuit', + groundset=self.groundset()) + elif new_type == 'vector': + return OrientedMatroid(self.vectors(), + key='vector', + groundset=self.groundset()) + elif new_type == 'covector': + return OrientedMatroid(self.covectors(), + key='covector', + groundset=self.groundset()) + else: + raise NotImplementedError("Type not implemented") def dual(self): """ From 54e148cd4cfa7b05c526f90753000a71e424833a Mon Sep 17 00:00:00 2001 From: lizzy Date: Mon, 31 Jul 2023 14:42:25 +0100 Subject: [PATCH 089/101] New function NewOrientedMatroid --- .../abstract_oriented_matroid.py | 16 +++------ oriented_matroids/vector_oriented_matroid.py | 34 +++++++++---------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py index 8a069c1..b7a61c7 100644 --- a/oriented_matroids/abstract_oriented_matroid.py +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -725,24 +725,16 @@ def covectors(self): raise NotImplementedError("Covectors not implemented") - def change_type(self, new_type=None): + def NewOrientedMatroid(self, new_type=None): ''' Returns an oriented matroid of type specified. ''' from oriented_matroids import OrientedMatroid if new_type == None: pass - elif new_type == 'circuit': - return OrientedMatroid(self.circuits(), - key='circuit', - groundset=self.groundset()) - elif new_type == 'vector': - return OrientedMatroid(self.vectors(), - key='vector', - groundset=self.groundset()) - elif new_type == 'covector': - return OrientedMatroid(self.covectors(), - key='covector', + elif new_type in AbstractOrientedMatroid.keys: + return OrientedMatroid(getattr(self, new_type + 's'), + key=new_type, groundset=self.groundset()) else: raise NotImplementedError("Type not implemented") diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index 5e5f14d..8ea116d 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -198,6 +198,21 @@ def _repr_(self): rep = "Vector oriented matroid" return rep + def circuits(self): + """ + Return the circuits. + + Given a vector oriented matroid, the set of circuits is the set + `Min(V)` which denotes the set of inclusion-minimal (nonempty) signed + subsets. + """ + from sage.combinat.posets.posets import Poset + from oriented_matroids import OrientedMatroid + # remove 0 + vecs = [v for v in self.vectors() if not v.is_zero()] + P = Poset([vecs, lambda x,y: x.is_restriction_of(y)]) + return P.minimal_elements() + def matroid(self): r""" Returns the underlying matroid. @@ -216,20 +231,5 @@ def matroid(self): Matroid of rank 1 on 2 elements with 2 bases """ - circOM = self.to_circuit() - return circOM.matroid() - - def circuits(self): - """ - Return the circuits. - - Given a vector oriented matroid, the set of circuits is the set - `Min(V)` which denotes the set of inclusion-minimal (nonempty) signed - subsets. - """ - from sage.combinat.posets.posets import Poset - from oriented_matroids import OrientedMatroid - # remove 0 - vecs = [v for v in self.vectors() if not v.is_zero()] - P = Poset([vecs, lambda x,y: x.is_restriction_of(y)]) - return P.minimal_elements() + circOM = self.NewOrientedMatroid(new_type='circuit') + return circOM.matroid() \ No newline at end of file From 5785900def114c3f1e41b63e616511eb6f385507 Mon Sep 17 00:00:00 2001 From: lizzy Date: Mon, 31 Jul 2023 16:20:49 +0100 Subject: [PATCH 090/101] Adding Error for bug found --- oriented_matroids/circuit_oriented_matroid.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 149329a..144d7e0 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -100,9 +100,13 @@ def __init__(self, data, groundset=None, category=None): # all elements if groundset is None and len(circuits) > 0: groundset = circuits[0].groundset() - for X in circuits: - if X.groundset() != groundset: - raise ValueError("Groundsets must be the same") + for i in range(len(circuits)): + if groundset != circuits[i].groundset(): + raise NameError("Please input an appropriate groundset or add zeros") + else: + for X in circuits: + if X.groundset() != groundset: + raise ValueError("Groundsets must be the same") self._circuits = circuits self._elements = circuits From 5de5c7afd8ee03d1fe237b97b642c7dbbfb97224 Mon Sep 17 00:00:00 2001 From: lizzy Date: Tue, 1 Aug 2023 11:01:12 +0100 Subject: [PATCH 091/101] fixing bug to include same groundset error --- oriented_matroids/circuit_oriented_matroid.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 144d7e0..8b818c1 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -99,11 +99,14 @@ def __init__(self, data, groundset=None, category=None): # If our groundset is none, make sure the groundsets are the same for # all elements if groundset is None and len(circuits) > 0: - groundset = circuits[0].groundset() - for i in range(len(circuits)): - if groundset != circuits[i].groundset(): - raise NameError("Please input an appropriate groundset or add zeros") + if len(data[0]) < 3: + groundset = [] + for X in circuits: + for el in X.groundset(): + if el not in groundset: + groundset.append(el) else: + groundset = circuits[0].groundset() for X in circuits: if X.groundset() != groundset: raise ValueError("Groundsets must be the same") From dfd655a1e948aaffa7b9744b730fd179ced88be0 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 2 Aug 2023 10:13:34 +0100 Subject: [PATCH 092/101] creating a more efficient groundset --- oriented_matroids/circuit_oriented_matroid.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 8b818c1..f5e86f3 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -102,9 +102,7 @@ def __init__(self, data, groundset=None, category=None): if len(data[0]) < 3: groundset = [] for X in circuits: - for el in X.groundset(): - if el not in groundset: - groundset.append(el) + groundset = list(set(groundset+X.groundset())) else: groundset = circuits[0].groundset() for X in circuits: From 38965e8fa6b2aa26d77cdab1e4c885ccbf6ce844 Mon Sep 17 00:00:00 2001 From: lizzy Date: Wed, 2 Aug 2023 14:58:49 +0100 Subject: [PATCH 093/101] Adding examples for convert_to and changing name --- oriented_matroids/abstract_oriented_matroid.py | 17 ++++++++++++++--- oriented_matroids/vector_oriented_matroid.py | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py index b7a61c7..c6d7bba 100644 --- a/oriented_matroids/abstract_oriented_matroid.py +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -725,15 +725,26 @@ def covectors(self): raise NotImplementedError("Covectors not implemented") - def NewOrientedMatroid(self, new_type=None): + def convert_to(self, new_type=None): ''' Returns an oriented matroid of type specified. + + EXAMPLES:: + + sage: from oriented_matroids import OrientedMatroid + sage: M = OrientedMatroid([[1],[-1],[0]], key='vector') + sage: M.convert_to('circuit') + Circuit oriented matroid of rank 0 + sage: M.convert_to() + Traceback (most recent call last): + ... + TypeError: Must be given a type to convert to ''' from oriented_matroids import OrientedMatroid if new_type == None: - pass + raise TypeError("Must be given a type to convert to") elif new_type in AbstractOrientedMatroid.keys: - return OrientedMatroid(getattr(self, new_type + 's'), + return OrientedMatroid(getattr(self, new_type + 's')(), key=new_type, groundset=self.groundset()) else: diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index 8ea116d..d96d1f4 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -231,5 +231,5 @@ def matroid(self): Matroid of rank 1 on 2 elements with 2 bases """ - circOM = self.NewOrientedMatroid(new_type='circuit') + circOM = self.convert_to('circuit') return circOM.matroid() \ No newline at end of file From 6cc6669bee768e25c0bb125fc8dea840b18a9d65 Mon Sep 17 00:00:00 2001 From: lizzy Date: Fri, 4 Aug 2023 10:10:17 +0100 Subject: [PATCH 094/101] Adding an example for error --- oriented_matroids/circuit_oriented_matroid.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index f5e86f3..912f310 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -145,6 +145,12 @@ def is_valid(self): Traceback (most recent call last): ... ValueError: Every element needs an opposite + + sage: C5 = [((1,),(3,),(2,)), ((1,2),(3,),(4,)), ((3,),(1,),(2,)), ((3,),(1,2),(4,))] + sage: OrientedMatroid(C5,key='circuit') + Traceback (most recent call last): + ... + ValueError: Groundsets must be the same """ circuits = self.circuits() From 680cb749a0d89753da0008d4b523632ad43674df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 10 Sep 2023 09:05:08 +0200 Subject: [PATCH 095/101] fixing a few details (rst, pycodestyle-minimal, code) --- docs/source/conf.py | 7 ++----- .../oriented_matroids_category.py | 6 +++--- oriented_matroids/signed_subset_element.py | 21 ++++++++----------- oriented_matroids/signed_vector_element.py | 18 +++++++--------- oriented_matroids/vector_oriented_matroid.py | 5 +---- 5 files changed, 23 insertions(+), 34 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 7c54d3c..b16c60d 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -29,8 +29,6 @@ except ImportError: raise RuntimeError("to build the documentation you need to be inside a Sage shell (run first the command 'sage -sh' in a shell") - - # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. @@ -66,8 +64,6 @@ # The master toctree document. master_doc = 'index' - - # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. @@ -322,13 +318,14 @@ exclude_patterns=['**/'+os.path.join(mathjax_relative, i) for i in ('docs', 'README*', 'test', 'unpacked', 'LICENSE')] else: - extensions.append('sphinx.ext.pngmath') + extensions.append('sphinx.ext.pngmath') # This is to make the verbatim font smaller; # Verbatim environment is not breaking long lines from sphinx.highlighting import PygmentsBridge from pygments.formatters.latex import LatexFormatter + class CustomLatexFormatter(LatexFormatter): def __init__(self, **options): super(CustomLatexFormatter, self).__init__(**options) diff --git a/oriented_matroids/oriented_matroids_category.py b/oriented_matroids/oriented_matroids_category.py index 69fbd2b..10b347d 100644 --- a/oriented_matroids/oriented_matroids_category.py +++ b/oriented_matroids/oriented_matroids_category.py @@ -6,7 +6,7 @@ # Copyright (C) 2019 Aram Dermenjian # # Distributed under the terms of the GNU General Public License (GPL) -# http://www.gnu.org/licenses/ +# https://www.gnu.org/licenses/ # ****************************************************************************** from sage.misc.abstract_method import abstract_method @@ -36,7 +36,7 @@ class OrientedMatroids(Category): and `Z^- \subseteq \left(X^- \cup Y^-\right) \backslash \left\{e\right\}`. - See :Wikipedia:`Oriented_matroid` for details. + See :wikipedia:`Oriented_matroid` for details. EXAMPLES:: @@ -209,7 +209,7 @@ def an_element(self): from sage.misc.prandom import randint els = self.elements() i = randint(1, len(els)) - return els[i-1] + return els[i - 1] def face_poset(self, facade=False): r""" diff --git a/oriented_matroids/signed_subset_element.py b/oriented_matroids/signed_subset_element.py index ae94a41..f0e21a4 100644 --- a/oriented_matroids/signed_subset_element.py +++ b/oriented_matroids/signed_subset_element.py @@ -34,11 +34,12 @@ class SignedSubsetElement(Element): generated by :class:`OrientedMatroid`. - ``data`` -- (default: ``None``) is a tuple with information. Can be given in one of the following formats: - + **as a vector** -- this is a tuple of pluses, minuses, and zeroes. - + **as three tuples** -- the first tuple is the positives, the second - the negatives and the third the zeroes. - + **as a dict** -- the dictionary should have keys *positives*, - *negatives*, and *zeroes*. + + - **as a vector** -- this is a tuple of pluses, minuses, and zeroes. + - **as three tuples** -- the first tuple is the positives, the second + the negatives and the third the zeroes. + - **as a dict** -- the dictionary should have keys *positives*, + *negatives*, and *zeroes*. - ``groundset`` -- (default: ``None``) if not given will construct the groundset from the parent, or if none is created in the parent, using the elements found in the data. @@ -70,8 +71,7 @@ class SignedSubsetElement(Element): -: 0: - Elements are also lazy loaded to return the sign of elements from the grou -ndset:: + Elements are also lazy loaded to return the sign of elements from the groundset:: sage: M = OrientedMatroid([[1],[-1]],key='circuit', groundset=['e']) sage: C = M.elements(); C[0] @@ -559,13 +559,10 @@ def is_simplicial(self): I = P.interval(P.bottom(), self) PP = P.sublattice(I) b = PP.breadth() - if len(I) == 2**b: - return True - return False + return len(I) == 2**b def is_zero(self): """ Return whether or not element is 0 """ - return len([1 for e in self.groundset() if self(e) != 0]) == 0 - + return not any(self(e) != 0 for e in self.groundset()) diff --git a/oriented_matroids/signed_vector_element.py b/oriented_matroids/signed_vector_element.py index 2350e50..cc8760d 100644 --- a/oriented_matroids/signed_vector_element.py +++ b/oriented_matroids/signed_vector_element.py @@ -33,11 +33,12 @@ class SignedVectorElement(SignedSubsetElement): generated by :class:`OrientedMatroid`. - ``data`` -- (default: ``None``) is a tuple with information. Can be given in one of the following formats: - + **as a vector** -- this is a tuple of pluses, minuses, and zeroes. - + **as three tuples** -- the first tuple is the positives, the second - the negatives and the third the zeroes. - + **as a dict** -- the dictionary should have keys *positives*, - *negatives*, and *zeroes*. + + - **as a vector** -- this is a tuple of pluses, minuses, and zeroes. + - **as three tuples** -- the first tuple is the positives, the second + the negatives and the third the zeroes. + - **as a dict** -- the dictionary should have keys *positives*, + *negatives*, and *zeroes*. - ``groundset`` -- (default: ``None``) if not given will construct the groundset from the parent, or if none is created in the parent, using the elements found in the data. @@ -74,12 +75,11 @@ class SignedVectorElement(SignedSubsetElement): - :class:`oriented_matroids.signed_subset_element.SignedSubsetElement` """ - def __init__(self, parent=None, data=None, groundset=None, \ + def __init__(self, parent=None, data=None, groundset=None, positives=None, negatives=None, zeroes=None): """ Initialize ``self``. """ - SignedSubsetElement.__init__( self, parent, data, groundset, positives, negatives, zeroes) @@ -98,7 +98,6 @@ def _repr_(self): sage: M = OrientedMatroid(C, key='covector') sage: SignedVectorElement(M,data = (1,1,-1)) (1,1,-1) - """ return "(" + ','.join([str(self(e)) for e in self.groundset()]) + ")" @@ -116,7 +115,6 @@ def _latex_(self): sage: M = OrientedMatroid(C, key='covector') sage: latex(SignedVectorElement(M,data = (1,1,-1))) \left(1,1,-1\right) - """ - ground_set = [str(self(e)) for e in self.groundset()] + ground_set = (str(self(e)) for e in self.groundset()) return "\\left(" + ','.join(ground_set) + "\\right)" diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index a453e43..d0e717a 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -217,7 +217,6 @@ def matroid(self): sage: M = OrientedMatroid(V, key='vector') sage: M.matroid() Matroid of rank 1 on 2 elements with 2 bases - """ circOM = self.to_circuit() return circOM.matroid() @@ -231,9 +230,7 @@ def circuits(self): subsets. """ from sage.combinat.posets.posets import Poset - from oriented_matroids import OrientedMatroid # remove 0 vecs = [v for v in self.vectors() if not v.is_zero()] - P = Poset([vecs, lambda x,y: x.is_restriction_of(y)]) + P = Poset([vecs, lambda x, y: x.is_restriction_of(y)]) return P.minimal_elements() - From f4b4ce4e1e3da6c8ebc687d760095d567f38239c Mon Sep 17 00:00:00 2001 From: Cali Garmo Date: Sun, 5 Nov 2023 10:48:01 +0400 Subject: [PATCH 096/101] Not all methods exist and so it should produce an error --- oriented_matroids/abstract_oriented_matroid.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py index c6d7bba..bb2fd7c 100644 --- a/oriented_matroids/abstract_oriented_matroid.py +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -744,11 +744,15 @@ def convert_to(self, new_type=None): if new_type == None: raise TypeError("Must be given a type to convert to") elif new_type in AbstractOrientedMatroid.keys: - return OrientedMatroid(getattr(self, new_type + 's')(), + try: + els = getattr(self, new_type + 's')() + except: + raise NotImplementedError("No %ss() method found in oriented matroid" % (new_type,)) + return OrientedMatroid(els, key=new_type, groundset=self.groundset()) else: - raise NotImplementedError("Type not implemented") + raise NotImplementedError("Type %s not implemented" % (new_type,)) def dual(self): """ From b5c1232d9ec2b9ec9070dae791dff49eaef735b9 Mon Sep 17 00:00:00 2001 From: Cali Garmo Date: Fri, 9 Feb 2024 12:30:43 +0100 Subject: [PATCH 097/101] Make documentation and file changes --- CHANGELOG.md | 12 + README.md | 5 +- docs/source/conf.py | 11 +- docs/source/index.rst | 5 +- ...gory.rst => abstract_oriented_matroid.rst} | 4 +- ...yperplane_arrangement_oriented_matroid.rst | 9 - ...yperplane_arrangement_oriented_matroid.rst | 9 + .../signed_vector_element.rst | 9 - makefile | 4 +- oriented_matroids/__init__.py | 4 +- .../abstract_oriented_matroid.py | 696 ++---------------- oriented_matroids/circuit_oriented_matroid.py | 4 +- .../covector_oriented_matroid.py | 18 +- oriented_matroids/oriented_matroid.py | 41 +- .../oriented_matroids_catalog.py | 2 +- ...hyperplane_arrangement_oriented_matroid.py | 12 +- oriented_matroids/signed_subset_element.py | 587 +++++++++++++++ oriented_matroids/vector_oriented_matroid.py | 49 +- setup.py | 8 +- 19 files changed, 744 insertions(+), 745 deletions(-) rename docs/source/oriented_matroids/{oriented_matroids_category.rst => abstract_oriented_matroid.rst} (52%) delete mode 100644 docs/source/oriented_matroids/hyperplane_arrangement_oriented_matroid.rst create mode 100644 docs/source/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.rst delete mode 100644 docs/source/oriented_matroids/signed_vector_element.rst create mode 100644 oriented_matroids/signed_subset_element.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ca3d68..2dce90b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,22 @@ All notable changes will be made in this file. ### Added +- (#18) Implemented Cocircuits and covectors. +- (#14) Added some additional examples to ensure tests catch potential errors. + ### Changed +- (#22) Updated the documentation to be more complete. +- (#12) Altered it so that the `to_xxx()` functions are encapsulated in the function `change_type()`. +- (#2) Updated package to fit into up to date methods for making packages. +- (#1) Restructed the OrientedMatroids class. In particular: + - Removed the category implementation and structured based off the matroid implementation. + - There is now an `AbstractOrientedMatroid` class which handles the abstract methods and everything pulls from here. + ### Fixed +- (#15) Fixed the groundset error bug. + ## [0.0.2] - 2020-12-15 diff --git a/README.md b/README.md index 117f8ef..ca49c78 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,10 @@ This package contains an oriented matroid implementation for sagemath. ## Current version -**NOTE:** This package currently does not work. If you would like to help with the development, please let Aram know. +The current version is 0.1.0 and is compatible with sagemath 10.0. It is in beta and is open for testing from others. + +**NOTE:** This package will be integrating into SageMath directly. If you see any errors while using this please, open an issue and let us know so we can correct it. -The current version is 0.1.0 and is compatible with sagemath 10.0. ## Installation diff --git a/docs/source/conf.py b/docs/source/conf.py index 7c54d3c..de7862a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -47,7 +47,8 @@ # ones. extensions = [ #'sphinx.ext.autodoc', - 'sage_autodoc', + #'sage_autodoc', + 'sage_docbuild.ext.sage_autodoc', 'sage_package.sphinx', 'sphinx.ext.doctest', 'sphinx.ext.coverage', @@ -232,7 +233,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', package_name + '.tex', u'Documentation of ' + unicode(package_name), + ('index', package_name + '.tex', u'Documentation of ' + str(package_name), authors, 'manual'), ] @@ -262,7 +263,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', package_name, unicode(package_name) + u" documentation", + ('index', package_name, str(package_name) + u" documentation", [authors], 1) ] @@ -276,7 +277,7 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', package_name, unicode(package_name) + u" documentation", + ('index', package_name, str(package_name) + u" documentation", authors, package_name, project, 'Miscellaneous'), ] @@ -322,7 +323,7 @@ exclude_patterns=['**/'+os.path.join(mathjax_relative, i) for i in ('docs', 'README*', 'test', 'unpacked', 'LICENSE')] else: - extensions.append('sphinx.ext.pngmath') + extensions.append('sphinx.ext.imgmath') # This is to make the verbatim font smaller; # Verbatim environment is not breaking long lines diff --git a/docs/source/index.rst b/docs/source/index.rst index e447f72..d392ff2 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -12,7 +12,7 @@ Oriented Matroids :maxdepth: 1 oriented_matroids/oriented_matroid - oriented_matroids/oriented_matroids_category + oriented_matroids/abstract_oriented_matroid Representations --------------- @@ -22,7 +22,7 @@ Representations oriented_matroids/circuit_oriented_matroid oriented_matroids/covector_oriented_matroid - oriented_matroids/hyperplane_arrangement_oriented_matroid + oriented_matroids/real_hyperplane_arrangement_oriented_matroid oriented_matroids/vector_oriented_matroid Elements @@ -32,7 +32,6 @@ Elements :maxdepth: 1 oriented_matroids/signed_subset_element - oriented_matroids/signed_vector_element Indices and Tables ================== diff --git a/docs/source/oriented_matroids/oriented_matroids_category.rst b/docs/source/oriented_matroids/abstract_oriented_matroid.rst similarity index 52% rename from docs/source/oriented_matroids/oriented_matroids_category.rst rename to docs/source/oriented_matroids/abstract_oriented_matroid.rst index 7fe01be..ccb7315 100644 --- a/docs/source/oriented_matroids/oriented_matroids_category.rst +++ b/docs/source/oriented_matroids/abstract_oriented_matroid.rst @@ -1,9 +1,9 @@ .. nodoctest -Oriented Matroids Category +Abstract Oriented Matroids ========================== -.. automodule:: oriented_matroids.oriented_matroids_category +.. automodule:: oriented_matroids.abstract_oriented_matroid :members: :undoc-members: :show-inheritance: diff --git a/docs/source/oriented_matroids/hyperplane_arrangement_oriented_matroid.rst b/docs/source/oriented_matroids/hyperplane_arrangement_oriented_matroid.rst deleted file mode 100644 index e75557a..0000000 --- a/docs/source/oriented_matroids/hyperplane_arrangement_oriented_matroid.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. nodoctest - -Hyperplane Arrangement Oriented Matroids -======================================== - -.. automodule:: oriented_matroids.hyperplane_arrangement_oriented_matroid - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.rst b/docs/source/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.rst new file mode 100644 index 0000000..43404ea --- /dev/null +++ b/docs/source/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.rst @@ -0,0 +1,9 @@ +.. nodoctest + +Real Hyperplane Arrangement Oriented Matroids +============================================= + +.. automodule:: oriented_matroids.real_hyperplane_arrangement_oriented_matroid + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/oriented_matroids/signed_vector_element.rst b/docs/source/oriented_matroids/signed_vector_element.rst deleted file mode 100644 index 593d6db..0000000 --- a/docs/source/oriented_matroids/signed_vector_element.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. nodoctest - -Signed Vectors -============== - -.. automodule:: oriented_matroids.signed_vector_element - :members: - :undoc-members: - :show-inheritance: diff --git a/makefile b/makefile index fced82d..e6c95dc 100644 --- a/makefile +++ b/makefile @@ -4,12 +4,12 @@ PACKAGE = oriented_matroids # change to your sage command if needed -SAGE = /sage/sagedev/sage +SAGE = /sage/sage/sage all: install test install: - $(SAGE) -pip install --upgrade --no-index -v . + $(SAGE) -pip install --upgrade --no-index --no-build-isolation -v . uninstall: $(SAGE) -pip uninstall $(PACKAGE) diff --git a/oriented_matroids/__init__.py b/oriented_matroids/__init__.py index af8d503..76eb000 100644 --- a/oriented_matroids/__init__.py +++ b/oriented_matroids/__init__.py @@ -2,6 +2,6 @@ from .oriented_matroid import OrientedMatroid from .abstract_oriented_matroid import AbstractOrientedMatroid -from sage.misc.lazy_import import lazy_import -#lazy_import('sage.matroids.oriented_matroids', +# from sage.misc.lazy_import import lazy_import +# lazy_import('sage.matroids.oriented_matroids', # 'oriented_matroids_catalog', 'oriented_matroids') diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py index c9f706f..a4dca9a 100644 --- a/oriented_matroids/abstract_oriented_matroid.py +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -1,11 +1,20 @@ # -*- coding: utf-8 -*- r""" -Category of Oriented Matroids +Abstract class for oriented matroids. + +AUTHORS: + +- Aram Dermenjian (2019-07-12): Initial version +- Elizabeth Flight (2023-08-01): Beta version +- Tudor Tanasa (2023-08-01): Beta version """ # ***************************************************************************** -# Copyright (C) 2019 Aram Dermenjian +# Copyright (C) 2019 Aram Dermenjian # # Distributed under the terms of the GNU General Public License (GPL) +# +# The full text of the GPL is available at: +# # http://www.gnu.org/licenses/ # ****************************************************************************** @@ -15,609 +24,12 @@ from sage.structure.parent import Parent from sage.categories.sets_cat import Sets from sage.structure.global_options import GlobalOptions +from oriented_matroids.signed_subset_element import SignedSubsetElement -from sage.structure.element import Element -import copy - -r""" -Signed Subset element ---------------------------------------- - -This implements a basic signed subet element which is used for oriented -matroids. - -AUTHORS: - -- Aram Dermenjian (2019-07-12): Initial version -""" - -############################################################################## -# Copyright (C) 2019 Aram Dermenjian -# -# Distributed under the terms of the GNU General Public License (GPL) -# -# The full text of the GPL is available at: -# -# http://www.gnu.org/licenses/ -############################################################################## - - -class SignedSubsetElement(Element): - r""" - Creates a signed subset. - - INPUT: - - - ``parent`` -- the parent object of the element. Usually is a class - generated by :class:`OrientedMatroid`. - - ``data`` -- (default: ``None``) is a tuple with information. Can be - given in one of the following formats: - + **as a vector** -- this is a tuple of pluses, minuses, and zeroes. - + **as three tuples** -- the first tuple is the positives, the second - the negatives and the third the zeroes. - + **as a dict** -- the dictionary should have keys *positives*, - *negatives*, and *zeroes*. - - - ``groundset`` -- (default: ``None``) if not given will construct - the groundset from the parent, or if none is created in the parent, - using the elements found in the data. - - ``positives`` -- (default: ``None``) alternative to ``data``. Should be - a tuple of elements. Requires ``negatives`` to be set. - - ``negatives`` -- (default: ``None``) alternative to ``data``. Should be - a tuple of elements. Requires ``positives`` to be set. - - ``zeroes`` -- (default: ``None``) alternative to ``data``. Should be a - tuple of elements. Requires ``positives`` and ``negatives`` to be set. - - EXAMPLES:: - - sage: from oriented_matroids.oriented_matroid import OrientedMatroid - sage: from oriented_matroids.abstract_oriented_matroid import SignedSubsetElement - sage: M = OrientedMatroid([[1],[-1]],key='circuit'); - sage: SignedSubsetElement(M,data = (0,)) - +: - -: - 0: 0 - sage: SignedSubsetElement(M,data = (1,)) - +: 0 - -: - 0: - sage: M = OrientedMatroid([[1],[-1]],key='circuit', groundset=['e']) - sage: SignedSubsetElement(M,data = (1,)) - +: e - -: - 0: - - Elements are also lazy loaded to return the sign of elements from the - groundset:: - - sage: M = OrientedMatroid([[1],[-1]],key='circuit', groundset=['e']) - sage: C = M.elements(); C[0] - +: e - -: - 0: - sage: C[0]('e') - 1 - - .. SEEALSO:: - - - :class:`oriented_matroids.oriented_Matroid.OrientedMatroid` - - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` - - """ - - def __init__(self, parent=None, data=None, groundset=None, - positives=None, negatives=None, zeroes=None): - """ - Initialize ``self``. - """ - # If our groundset isn't set but our parent has one, use its groundset - if groundset is None: - try: - groundset = parent.groundset() - except AttributeError: - groundset = None - - # remove parent if data not present - if parent is None \ - or (data is None and groundset is None and positives is None): - from sage.structure.parent import Parent - data = parent - parent = Parent() - - # instantiate! - self._p = set([]) - self._n = set([]) - self._z = set([]) - - # If we're setting things one item at a time - if positives is not None: - if negatives is None: - raise ValueError( - "If positives is set, negatives must be as well") - - self._p = set(positives) - self._n = set(negatives) - if zeroes is None: - if groundset is None: - self._z = set([]) - else: - gs = set(groundset) - self._z = gs.difference(self._p).difference(self._n) - else: - self._z = set(zeroes) - - # If we already have a signed subset element, use it's data - elif isinstance(data, SignedSubsetElement): - self._p = data.positives() - self._n = data.negatives() - self._z = data.zeroes() - - # If we have a tuple, use its information - elif isinstance(data, tuple): - # if we're given vector format - if data[0] in [-1, 0, 1, '+', '0', '-', '']: - if groundset is not None and len(data) != len(groundset): - raise ValueError( - "Length of vector must be same number of elements as ground set") - for i, j in enumerate(data): - label = i - if groundset is not None: - label = groundset[i] - if j == -1 or j == '-': - self._n.add(label) - elif j == 1 or j == '+': - self._p.add(label) - elif j == 0 or j == '' or j == '0': - self._z.add(label) - else: - raise ValueError("Must be tuple of -1, 0, 1") - - # If we have a tuple of tuples - else: - self._p = set(data[0]) - self._n = set(data[1]) - if len(data) > 2: - self._z = set(data[2]) - elif groundset is not None: - self._z = set(groundset).difference( - self._p).difference(self._n) - # If we have a dictionary, use the keys to figure it out - elif isinstance(data, dict): - if 'p' in data: - self._p = data['p'] - if 'positives' in data: - self._p = data['positives'] - if 'n' in data: - self._n = data['n'] - if 'negatives' in data: - self._n = data['negatives'] - if 'z' in data: - self._z = data['z'] - if 'zeroes' in data: - self._z = data['zeroes'] - else: - raise ValueError( - "Either positives and negatives are set or data is a tuple, OrientedMatroidELement or a dict") - - # Type fix - self._p = set(self._p) - self._n = set(self._n) - self._z = set(self._z) - - # Setup the ground set if it's not set yet - if groundset is None: - self._g = list(self._p.union(self._n).union(self._z)) - else: - if not self.support().union(self.zeroes()).issubset(groundset): - raise ValueError("Elements must appear in groundset") - - # Update the zeroes with everything in the ground set - if self._z is None: - self._z = set(groundset).difference(self.support()) - - # ground set should be everything - if not set(groundset).issubset(self.support().union(self.zeroes())): - raise ValueError( - "Every element must be either positive, negative or zero") - self._g = groundset - - self._g = list(self._g) - - Element.__init__(self, parent) - - def __call__(self, var): - """ - Return the sign of an element in the groundset. - """ - - if var in self.positives(): - return 1 - if var in self.negatives(): - return -1 - if var in self.zeroes(): - return 0 - raise ValueError("Not in groundset") - - def __hash__(self): - """ - Return hashed string of signed subset. - """ - fsp = frozenset(self._p) - fsn = frozenset(self._n) - fsz = frozenset(self._z) - return hash((fsp, fsn, fsz)) - - def __neg__(self): - """ - Return the opposite signed subset. - """ - N = copy.copy(self) - N._p = self._n - N._n = self._p - return N - - def __eq__(self, other): - """ - Return whether two elements are equal. - """ - if isinstance(other, SignedSubsetElement): - if self._p == other._p \ - and self._n == other._n \ - and self._z == other._z: - return True - return False - - def __ne__(self, other): - """ - Return whether two elements are not equal. - """ - return not (self == other) - - def _cmp_(self, other): - """ - Arbitrary comparison function so posets work. - """ - if not isinstance(other, SignedSubsetElement): - return 0 - return 1 - # x = len(self.support()) - len(other.support()) - # if x == 0: - # return x - # return x / abs(x) * -1 - - def __bool__(self): - r""" - Returns whether an element is not considered a zero. - - For an oriented matroid, we consider the empty set - `\emptyset = (\emptyset,\emptyset)` to be a zero as - it is the same as the all zero vector. - """ - if len(self.support()) > 0: - return True - return False - - def __iter__(self): - """ - Returns an iter version of self. - """ - for e in self.groundset(): - yield self(e) - - def _repr_(self): - """ - Return a string of the signed subset. - - EXAMPLES:: - - sage: from oriented_matroids.oriented_matroid import OrientedMatroid - sage: from oriented_matroids.abstract_oriented_matroid import SignedSubsetElement - sage: C = [ ((1,4),(2,3)) , ((2,3),(1,4)) ] - sage: M = OrientedMatroid(C,key='circuit') - sage: SignedSubsetElement(M,data = ((1,4),(2,3))) - +: 1,4 - -: 2,3 - 0: - - """ - - if AbstractOrientedMatroid.options.display == 'set': - p = map(str, self.positives()) - n = map(str, self.negatives()) - z = map(str, self.zeroes()) - return "+: " + ','.join(p) + "\n" + \ - "-: " + ','.join(n) + "\n" +\ - "0: " + ','.join(z) - if AbstractOrientedMatroid.options.display == 'vector': - return "(" + ','.join([str(self(e)) for e in self.groundset()]) + ")" - - def _latex_(self): - r""" - Return a latex representation of the signed subset. - - EXAMPLES:: - - sage: from oriented_matroids.oriented_matroid import OrientedMatroid - sage: from oriented_matroids.abstract_oriented_matroid import SignedSubsetElement - sage: C = [ ((1,4),(2,3)) , ((2,3),(1,4)) ] - sage: M = OrientedMatroid(C,key='circuit') - sage: latex(SignedSubsetElement(M,data = ((1,4),(2,3)))) - \left( \left{1,4\right},\left{2,3\right} \right) - - """ - if AbstractOrientedMatroid.options.display == 'set': - p = map(str, self.positives()) - n = map(str, self.negatives()) - return "\\left( \\left{" + ','.join(p) + \ - "\\right},\\left{" + ','.join(n) + "\\right} \\right)" - if AbstractOrientedMatroid.options.display == 'vector': - ground_set = [str(self(e)) for e in self.groundset()] - return "\\left(" + ','.join(ground_set) + "\\right)" - - def __copy__(self): - """ - Return a copy of the element - """ - return SignedSubsetElement(parent=self.parent(), groundset=self.groundset(), positives=self.positives(), negatives=self.negatives(), zeroes=self.zeroes()) - - def __deepcopy__(self): - """ - Return a copy of the element - """ - return SignedSubsetElement(parent=self.parent(), groundset=self.groundset(), positives=self.positives(), negatives=self.negatives(), zeroes=self.zeroes()) - - def to_list(self): - """ - Convert objcet to a list - """ - return eval("[" + ','.join([str(self(e)) for e in self.groundset()]) + "]") - - def positives(self): - """ - Return the set of positives. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: M = OrientedMatroid([[1,-1,1],[-1,1,-1]], key='circuit') - sage: E = M.elements()[0] - sage: E.positives() - {0, 2} - - """ - return self._p - - def negatives(self): - """ - Return the set of negatives. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: M = OrientedMatroid([[1,-1,1],[-1,1,-1]], key='circuit') - sage: E = M.elements()[0] - sage: E.negatives() - {1} - - """ - return self._n - - def zeroes(self): - r""" - Return the set of zeroes. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') - sage: E = M.elements()[0] - sage: E.zeroes() - {2} - - """ - return self._z - - def support(self): - r""" - Return the support set. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') - sage: E = M.elements()[0] - sage: E.support() - {0, 1} - - """ - return self._p.union(self._n) - - def groundset(self): - r""" - Return the ground set. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') - sage: E = M.elements()[0] - sage: E.groundset() - [0, 1, 2] - - """ - return self._g - - def composition(self, other): - r""" - Return the composition of two elements. - - The composition of two elements `X` and `Y`, - denoted `X \circ Y` is given componentwise - where for `e \in E` we have `(X \circ Y)(e) = X(e)` - if `X(e) \neq 0` else it equals `Y(e)`. - - EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid - sage: from oriented_matroids import AbstractOrientedMatroid - sage: AbstractOrientedMatroid.options.display='vector' - sage: M = OrientedMatroid([[0],[1],[-1]], key='vector') - sage: E1 = M.elements()[0]; E2 = M.elements()[1] - sage: E1.composition(E2) - (1) - sage: E2.composition(E1) - (1) - sage: E1.composition(E2) == E2.composition(E1) - True - - """ - p = [] - n = [] - z = [] - for e in self.groundset(): - x = self(e) - # If x is non-zero, keep its value - if x == 1: - p.append(e) - elif x == -1: - n.append(e) - else: - # else grab the value of the other - x = other(e) - if x == 1: - p.append(e) - elif x == -1: - n.append(e) - else: - z.append(e) - return type(self)(self.parent(), positives=p, negatives=n, zeroes=z) - - def separation_set(self, other): - r""" - Return the separation set between two elements. - - The separation set of two elements `X` and `Y` - is given by `S(X,Y) = \left\{e \mid X(e) = -Y(e) \neq 0 \right\}` - """ - return self.positives().intersection(other.negatives()).union(self.negatives().intersection(other.positives())) - - def reorientation(self, change_set): - r""" - Return the reorientation by a set. - - The reorientation of `X` by some `A \subseteq E` is - the signed subset (covector) given by `{}_{-A}X` where - `{}_{-A}X^+ = (X^+ \backslash A) \cup (X^- \cap A)` and similarly for - `{}_{-A}X^-`. - """ - if change_set in self.groundset(): - change_set = set([change_set]) - else: - change_set = set(change_set) - - # ensure every elt is in the groundset - for i in change_set: - if i not in self.groundset(): - raise ValueError("{} is not in the ground set".format(i)) - - p = self.positives().difference(change_set).union( - self.negatives().intersection(change_set)) - n = self.negatives().difference(change_set).union( - self.positives().intersection(change_set)) - return type(self)(self.parent(), positives=p, negatives=n, groundset=self.groundset()) - - def is_conformal_with(self, other): - r""" - Return if the two elements are conformal. - - Two elements `X` and `Y` are *conformal* if - `S(X,Y) = \emptyset`. This is true if and only if `X^+ \subseteq Y^+` - and `X^- \subseteq Y^-`. - """ - return len(self.separation_set(other)) == 0 - - def is_restriction_of(self, other): - r""" - Return if `self` is a restriction of `other`. - - A signed subset `X` is a *restriction* of a signed subset `Y` if - `X^+ \subsetex Y^+` and `X^- \subseteq Y^-`. If `X` is a restriction of - `Y` we sometimes say `X` conforms to `Y`. This should not be mistaken - with *is conformal with*. - """ - return self.positives().issubset(other.positives()) \ - and self.negatives().issubset(other.negatives()) - - def is_tope(self): - r""" - Return whether object is a tope. - - A covector is a tope if it is a maximal - element in the face poset. - - .. WARNING:: - - Requires the method `face_lattice` to exist in the oriented - matroid. - """ - if getattr(self.parent(), 'face_lattice', None) is not None: - raise TypeError( - "Topes are only implemented if .face_lattice() is implemented") - - return self in self.parent().topes() - - def is_simplicial(self): - r""" - Return whether or not a tope is simplicial. - - A tope `T` is simplicial if the interval `[0,T]` is boolean - in the face lattice. We note that the breadth of a lattice - can characterize this. In particular a lattice of breadth `n` - contains a sublattice isomorphic to the Boolean lattice of `2^n` - elements. In other words, if `[0,T]` has `2^n` elements and - the breadth of `[0,T]` is `n` then the interval is boolean - and thus `T` is simplicial. - """ - if not self.is_tope(): - raise TypeError("Only topes can be simplicial") - - P = self.parent().face_lattice() - I = P.interval(P.bottom(), self) - PP = P.sublattice(I) - b = PP.breadth() - if len(I) == 2**b: - return True - return False - - def is_zero(self): - """ - Return whether or not element is 0 - """ - return len([1 for e in self.groundset() if self(e) != 0]) == 0 - class AbstractOrientedMatroid(UniqueRepresentation, Parent): r""" - The category of oriented matroids. - - Given a set `E` a signed subset of `E` is a pair `X = (X^+,X^-)` where - `X^+,X^- \subseteq E` and `X^+ \cap X^- = \emptyset`. The support of `X` - is the set `\underline{X} = X^+ \cup X^-`. An *oriented matroid* is a - pair `M = (E,\mathcal{C})` where `E` is a set and `\mathcal{C}` is a - collection of signed subsets of `E` that satisfy certain axioms. An example - of these axioms are the circuit axioms: - - - `\emptyset \not\in \mathcal{C}` - - `\mathcal{C}= -\mathcal{C}` - - for all `X,Y \in \mathcal{C}`, - if `\underline{X} \subseteq \underline{Y}` then `X = Y` or `X = -Y`. - - for all `X,Y \in \mathcal{C}`, `X \neq -Y`, and `e \in X^+ \cap Y^-` - there is a `Z \in \mathcal{C}` such that - `Z^+ \subseteq \left(X^+ \cup Y^+\right) \backslash \left\{e\right\}` - and - `Z^- \subseteq \left(X^- \cup Y^-\right) \backslash \left\{e\right\}`. - - See :wikipedia:`Oriented_matroid` for details. + Abstract class for oriented matroids. .. SEEALSO:: @@ -633,7 +45,7 @@ class AbstractOrientedMatroid(UniqueRepresentation, Parent): class options(GlobalOptions): r""" - xxx + Options for oriented matroids. @OPTIONS@ @@ -673,7 +85,7 @@ def groundset(self): EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: A = hyperplane_arrangements.braid(2) sage: M = OrientedMatroid(A); M.groundset() (Hyperplane t0 - t1 + 0,) @@ -694,10 +106,10 @@ def elements(self): def circuits(self): """ Return all circuits. - + EXAMPLES:: - - sage: from oriented_matroids import OrientedMatriod + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: M = OrientedMatroid([[1],[-1]],key='circuit') sage: M.circuits() [+: 0 @@ -707,7 +119,7 @@ def circuits(self): -: 0 0: ] """ - if "_circuits" in dir(self): + if hasattr(self, "_circuits"): return self._circuits raise NotImplementedError("Circuits not implemented") @@ -715,7 +127,7 @@ def cocircuits(self): """ Return all cocircuits. """ - if "_cocircuits" in dir(self): + if hasattr(self, "_cocircuits"): return self._cocircuits raise NotImplementedError("Cocircuits not implemented") @@ -723,7 +135,7 @@ def vectors(self): """ Return all vectors. """ - if "_vectors" in dir(self): + if hasattr(self, "_vectors"): return self._vectors raise NotImplementedError("Vectors not implemented") pass @@ -732,18 +144,17 @@ def covectors(self): """ Return all covectors. """ - if "_covectors" in dir(self): + if hasattr(self, "_covectors"): return self._covectors raise NotImplementedError("Covectors not implemented") - - + def convert_to(self, new_type=None): ''' - Returns an oriented matroid of type specified. + Return an oriented matroid of type specified. EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: M = OrientedMatroid([[1],[-1],[0]], key='vector') sage: M.convert_to('circuit') Circuit oriented matroid of rank 0 @@ -752,8 +163,8 @@ def convert_to(self, new_type=None): ... TypeError: Must be given a type to convert to ''' - from oriented_matroids import OrientedMatroid - if new_type == None: + from oriented_matroids.oriented_matroid import OrientedMatroid + if new_type is None: raise TypeError("Must be given a type to convert to") elif new_type in AbstractOrientedMatroid.keys: try: @@ -769,10 +180,10 @@ def convert_to(self, new_type=None): def dual(self): """ Return the dual oriented matroid. - + EXAMPLES:: - - sage: from oriented_matroids import OrientedMatroid + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: A = hyperplane_arrangements.braid(3) sage: M = OrientedMatroid(A) sage: m = M.matroid() @@ -786,7 +197,7 @@ def dual(self): @cached_method def matroid(self): r""" - Returns the underlying matroid. + Return the underlying matroid. """ pass @@ -800,7 +211,7 @@ def rank(self): EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: A = hyperplane_arrangements.braid(3) sage: M = OrientedMatroid(A); M.rank() 2 @@ -812,24 +223,25 @@ def rank(self): def an_element(self): """ - Returns an arbitrary element. - + Return an arbitrary element. + EXAMPLES:: - + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: D = DiGraph({'v1':{'v2':1,'v3':2,'v4':3},'v2':{'v3':4,'v4':5},'v3':{'v4':6}}) sage: M = OrientedMatroid(D,key="circuit") sage: M.an_element() in M.circuits() True - + """ from sage.misc.prandom import randint els = self.elements() i = randint(1, len(els)) - return els[i-1] + return els[i - 1] def face_poset(self, facade=False): r""" - Returns the (big) face poset. + Return the (big) face poset. The *(big) face poset* is the poset on covectors such that `X \leq Y` if and only if `S(X,Y) = \emptyset` and @@ -837,7 +249,7 @@ def face_poset(self, facade=False): EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], ....: [0,0,0]] @@ -857,14 +269,14 @@ def face_poset(self, facade=False): def face_lattice(self, facade=False): r""" - Returns the (big) face lattice. + Return the (big) face lattice. The *(big) face lattice* is the (big) face poset with a top element added. EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1], ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0], ....: [0,0,0]] @@ -900,7 +312,7 @@ def face_lattice(self, facade=False): def topes(self): r""" - Returns the topes. + Return the topes. A *tope* is the maximal covector in the face poset. """ @@ -908,7 +320,7 @@ def topes(self): def tope_poset(self, base_tope, facade=False): r""" - Returns the tope poset. + Return the tope poset. The tope poset is the poset `(\mathcal{T}, B)` where `\mathcal{T}` is the set of topes and `B` is a distinguished tope called the @@ -929,7 +341,7 @@ def tope_poset(self, base_tope, facade=False): def is_simplicial(self): r""" - Returns if the oriented matroid is simplicial. + Return if the oriented matroid is simplicial. An oriented matroid is *simplicial* if every tope is simplicial. @@ -957,7 +369,7 @@ def is_acyclic(self): def deletion(self, change_set): r""" - Returns a covector oriented matroid of a deletion. + Return a covector oriented matroid of a deletion. Let `M = (E, \mathcal{L})` be an oriented matroid over a set `E` and a set of covectors `\mathcal{L}`. Given `A \subseteq E`, the @@ -970,7 +382,7 @@ def deletion(self, change_set): EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid """ if change_set in self.groundset(): @@ -989,12 +401,12 @@ def deletion(self, change_set): data.append((p, n, z)) data = deep_tupler(data) - from oriented_matroids import OrientedMatroid + from oriented_matroids.oriented_matroid import OrientedMatroid return OrientedMatroid(data, key='covector', groundset=groundset) def restriction(self, change_set): r""" - Returns a covector oriented matroid of a restriction. + Return a covector oriented matroid of a restriction. Given an oriented matroid `M = (E, \mathcal{L})` where `E` is a set and `\mathcal{L}` is the set of covectors. Given @@ -1031,12 +443,12 @@ def restriction(self, change_set): data.append((p, n, z)) data = deep_tupler(data) - from oriented_matroids import OrientedMatroid + from oriented_matroids.oriented_matroid import OrientedMatroid return OrientedMatroid(data, key='covector', groundset=groundset) def loops(self): r""" - Returns the loops of an oriented matroid. + Return the loops of an oriented matroid. A *loop* is an element `e \in E` such that there is a tope `T \in \mathcal{T}` with `T(e) = 0`. In particular @@ -1053,7 +465,7 @@ def loops(self): def are_parallel(self, e, f): r""" - Returns whether two elements in ground set are parallel. + Return whether two elements in ground set are parallel. Two elements in the ground set `e, f \in E` are parallel if they are not loops and for all `X \in \mathcal{C}`, `X(e) = 0` @@ -1070,7 +482,7 @@ def are_parallel(self, e, f): def is_simple(self): r""" - Returns if the oriented matroid is simple. + Return if the oriented matroid is simple. An oriented matroid is *simple* if there are no loops and no parallel elements. @@ -1092,4 +504,4 @@ def _element_constructor_(self, x): return x return False except ValueError: - return False \ No newline at end of file + return False diff --git a/oriented_matroids/circuit_oriented_matroid.py b/oriented_matroids/circuit_oriented_matroid.py index 1e11d3b..38607c7 100644 --- a/oriented_matroids/circuit_oriented_matroid.py +++ b/oriented_matroids/circuit_oriented_matroid.py @@ -10,7 +10,7 @@ """ ############################################################################## -# Copyright (C) 2019 Aram Dermenjian +# Copyright (C) 2019 Aram Dermenjian # # Distributed under the terms of the GNU General Public License (GPL) # @@ -149,7 +149,7 @@ def is_valid(self): Traceback (most recent call last): ... ValueError: Every element needs an opposite - + sage: C5 = [((1,),(3,),(2,)), ((1,2),(3,),(4,)), ((3,),(1,),(2,)), ((3,),(1,2),(4,))] sage: OrientedMatroid(C5,key='circuit') Traceback (most recent call last): diff --git a/oriented_matroids/covector_oriented_matroid.py b/oriented_matroids/covector_oriented_matroid.py index 9868486..1cb81a3 100644 --- a/oriented_matroids/covector_oriented_matroid.py +++ b/oriented_matroids/covector_oriented_matroid.py @@ -10,7 +10,7 @@ """ ############################################################################## -# Copyright (C) 2019 Aram Dermenjian +# Copyright (C) 2019 Aram Dermenjian # # Distributed under the terms of the GNU General Public License (GPL) # @@ -22,8 +22,6 @@ from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid from sage.categories.sets_cat import Sets -import copy - class CovectorOrientedMatroid(AbstractOrientedMatroid): r""" @@ -46,14 +44,14 @@ class CovectorOrientedMatroid(AbstractOrientedMatroid): INPUT: - - ``data`` -- a tuple containing SignedVectorElement elements or data - that can be used to construct :class:`SignedVectorElement` elements + - ``data`` -- a tuple containing SignedSubsetElement elements or data + that can be used to construct :class:`SignedSubsetElement` elements - ``goundset`` -- (default: ``None``) is the groundset for the data. If not provided, we grab the data from the signed subsets. EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: M = OrientedMatroid([[1],[-1],[0]], groundset=['e'], key='covector') sage: M Covector oriented matroid of rank 1 @@ -75,7 +73,7 @@ class CovectorOrientedMatroid(AbstractOrientedMatroid): .. SEEALSO:: :class:`oriented_matroids.oriented_matroid.OrientedMatroid` - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` + :class:`oriented_matroids.abstract_oriented_matroid.AbstractOrientedMatroid` """ @staticmethod @@ -156,7 +154,6 @@ def is_valid(self): Traceback (most recent call last): ... ValueError: weak elimination failed - """ covectors = self.covectors() @@ -218,12 +215,9 @@ def matroid(self): sage: M = OrientedMatroid(C, key='covector') sage: M.matroid() Matroid of rank 2 on 3 elements - - """ from sage.matroids.constructor import Matroid from sage.combinat.posets.posets import Poset flats = list(set([frozenset(X.zeroes()) for X in self.elements()])) - inc = lambda a,b: a.issubset(b) - rf = Poset((flats, inc)).rank_function() + rf = Poset((flats, lambda a, b: a.issubset(b))).rank_function() return Matroid(groundset=self.groundset(), rank_function=rf) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 919a06a..9372a1b 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -5,27 +5,42 @@ Theory ====== -Oriented matroids are ... +Oriented matroids are a generalization of directed graphs, central hyperplane +arrangements, vector arrangements and other mathematical objects. There are +many cryptomorphic definitions of oriented matroids. Precise definitions +for each type can be found in that classes directory. + +See :wikipedia:`Oriented_matroid` for more details. + Built-in oriented matroids ========================== -... +The current defined types of oriented matroids implemented into sage are: + - Circuit Oriented Matroids + - Covector Oriented Matroids + - Vector Oriented Matroids + - (Real) Hyperplane Arrangement Oriented Matroids Constructing oriented matroids ============================== -To define your own oriented matroid,... +To define your own oriented matroid, you can call the function +`OrientedMatroids(data, key)` where `data` is the data of the oriented matroid +and the `key` is the type of oriented matroid you are constructing. In the case +you pass in an object for the data (such as a hyperplane arrangement, digraph, +etc.) the code will try and create an oriented matroid for you. AUTHORS: -- Aram Dermenjian (2019-07-12): initial version - +- Aram Dermenjian (2019-07-12): Initial version +- Elizabeth Flight (2023-08-01): Beta version +- Tudor Tanasa (2023-08-01): Beta version """ # ***************************************************************************** -# Copyright (C) 2019 Aram Dermenjian +# Copyright (C) 2019 Aram Dermenjian # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -69,7 +84,6 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): + A list or tuple of + :class:`SignedSubsetElement` - + :class:`SignedVectorElement` + A tuple with positive, negative, and zero sets. - ``key`` -- (default: ``None``) is the representation of the @@ -85,8 +99,8 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid - sage: from oriented_matroids import AbstractOrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid sage: A = hyperplane_arrangements.braid(3) sage: M = OrientedMatroid(A); M @@ -137,11 +151,10 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): .. TODO:: - Currently chirotopes are not implemented - - We need a way to go from one type to another .. SEEALSO:: - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` + :class:`oriented_matroids.abstract_oriented_matroid.AbstractOrientedMatroid` REFERENCES: @@ -185,7 +198,7 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): # Add minus edges to properly get cycles for e in edges: - digraph.add_edge(e[1], e[0], "NEG_"+str(e[2])) + digraph.add_edge(e[1], e[0], "NEG_" + str(e[2])) groundset.append(str(e[2])) # Each cycle defines a circuit data = [] @@ -193,7 +206,7 @@ def OrientedMatroid(data=None, groundset=None, key=None, **kwds): p = set([]) n = set([]) for e in range(len(c) - 1): - e = str(digraph.edge_label(c[e], c[e+1])) + e = str(digraph.edge_label(c[e], c[e + 1])) if e.startswith('NEG_'): n.add(e.strip('NEG_')) else: @@ -261,4 +274,4 @@ def deep_tupler(obj): """ if isinstance(obj, list) or isinstance(obj, set): return tuple([deep_tupler(i) for i in obj]) - return obj \ No newline at end of file + return obj diff --git a/oriented_matroids/oriented_matroids_catalog.py b/oriented_matroids/oriented_matroids_catalog.py index 5b6fb4f..8bc8021 100644 --- a/oriented_matroids/oriented_matroids_catalog.py +++ b/oriented_matroids/oriented_matroids_catalog.py @@ -8,4 +8,4 @@ # Do not add code to this file, only imports. # user-accessible: -# from sage.matroids.catalog import ... +# from oriented_matroids.catalog import ... diff --git a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py index 230c827..2f214e3 100644 --- a/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py +++ b/oriented_matroids/real_hyperplane_arrangement_oriented_matroid.py @@ -10,7 +10,7 @@ """ ############################################################################## -# Copyright (C) 2019 Aram Dermenjian +# Copyright (C) 2019 Aram Dermenjian # # Distributed under the terms of the GNU General Public License (GPL) # @@ -18,11 +18,10 @@ # # http://www.gnu.org/licenses/ ############################################################################## - - from oriented_matroids.covector_oriented_matroid import CovectorOrientedMatroid from sage.categories.sets_cat import Sets + class RealHyperplaneArrangementOrientedMatroid(CovectorOrientedMatroid): r""" An oriented matroid implemented from a real hyperplane arrangement. @@ -60,7 +59,8 @@ class RealHyperplaneArrangementOrientedMatroid(CovectorOrientedMatroid): .. SEEALSO:: :class:`oriented_matroids.oriented_matroid.OrientedMatroid` - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` + :class:`oriented_matroids.abstract_oriented_matroid.AbstractOrientedMatroid` + :class:`sage.geometry.hyperplane_arrangement.arrangement.HyperplaneArrangementElement` """ @staticmethod @@ -108,8 +108,7 @@ def is_valid(self): """ if not self.arrangement().is_central(): - raise ValueError( - "Hyperplane arrangements must be central to be an oriented matroid.") + raise ValueError("Hyperplane arrangements must be central to be an oriented matroid.") return True @@ -140,7 +139,6 @@ def deletion(self, hyperplanes): sage: G = Graph({1:[2,4],2:[3,4,5],3:[4,6,8],4:[7],5:[8]}) sage: A = hyperplane_arrangements.graphical(G) sage: H = [A.hyperplanes()[i] for i in range(2,5)] - sage: M = OrientedMatroid(A) sage: M = OrientedMatroid(A); M Hyperplane arrangement oriented matroid of rank 7 sage: M2 = M.deletion(H); M2 diff --git a/oriented_matroids/signed_subset_element.py b/oriented_matroids/signed_subset_element.py new file mode 100644 index 0000000..1b600eb --- /dev/null +++ b/oriented_matroids/signed_subset_element.py @@ -0,0 +1,587 @@ +# -*- coding: utf-8 -*- +r""" +Abstract class for oriented matroids. + +AUTHORS: + +- Aram Dermenjian (2019-07-12): Initial version +- Elizabeth Flight (2023-08-01): Beta version +- Tudor Tanasa (2023-08-01): Beta version +""" +# ***************************************************************************** +# Copyright (C) 2019 Aram Dermenjian +# +# Distributed under the terms of the GNU General Public License (GPL) +# +# The full text of the GPL is available at: +# +# http://www.gnu.org/licenses/ +# ****************************************************************************** +from sage.structure.element import Element +import copy + + +class SignedSubsetElement(Element): + r""" + Implements a basic signed subset element which is used for the + oriented matroids class. + + INPUT: + + - ``parent`` -- the parent object of the element. Usually is a class + generated by :class:`OrientedMatroid`. + - ``data`` -- (default: ``None``) is a tuple with information. Can be + given in one of the following formats: + + **as a vector** -- this is a tuple of pluses, minuses, and zeroes. + + **as three tuples** -- the first tuple is the positives, the second + the negatives and the third the zeroes. + + **as a dict** -- the dictionary should have keys *positives*, + *negatives*, and *zeroes*. + + - ``groundset`` -- (default: ``None``) if not given will construct + the groundset from the parent, or if none is created in the parent, + using the elements found in the data. + - ``positives`` -- (default: ``None``) alternative to ``data``. Should be + a tuple of elements. Requires ``negatives`` to be set. + - ``negatives`` -- (default: ``None``) alternative to ``data``. Should be + a tuple of elements. Requires ``positives`` to be set. + - ``zeroes`` -- (default: ``None``) alternative to ``data``. Should be a + tuple of elements. Requires ``positives`` and ``negatives`` to be set. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: from oriented_matroids.signed_subset_element import SignedSubsetElement + sage: M = OrientedMatroid([[1],[-1]],key='circuit'); + sage: SignedSubsetElement(M,data = (0,)) + +: + -: + 0: 0 + sage: SignedSubsetElement(M,data = (1,)) + +: 0 + -: + 0: + sage: M = OrientedMatroid([[1],[-1]],key='circuit', groundset=['e']) + sage: SignedSubsetElement(M,data = (1,)) + +: e + -: + 0: + + Elements are also lazy loaded to return the sign of elements from the + groundset:: + + sage: M = OrientedMatroid([[1],[-1]],key='circuit', groundset=['e']) + sage: C = M.elements(); C[0] + +: e + -: + 0: + sage: C[0]('e') + 1 + + .. SEEALSO:: + + - :class:`oriented_matroids.oriented_matroid.OrientedMatroid` + - :class:`oriented_matroids.abstract_oriented_matroid.AbstractOrientedMatroid` + + """ + + def __init__(self, parent=None, data=None, groundset=None, + positives=None, negatives=None, zeroes=None): + """ + Initialize ``self``. + """ + # If our groundset isn't set but our parent has one, use its groundset + if groundset is None: + try: + groundset = parent.groundset() + except AttributeError: + groundset = None + + # remove parent if data not present + if parent is None \ + or (data is None and groundset is None and positives is None): + from sage.structure.parent import Parent + data = parent + parent = Parent() + + # instantiate! + self._p = set([]) + self._n = set([]) + self._z = set([]) + + # If we're setting things one item at a time + if positives is not None: + if negatives is None: + raise ValueError( + "If positives is set, negatives must be as well") + + self._p = set(positives) + self._n = set(negatives) + if zeroes is None: + if groundset is None: + self._z = set([]) + else: + gs = set(groundset) + self._z = gs.difference(self._p).difference(self._n) + else: + self._z = set(zeroes) + + # If we already have a signed subset element, use it's data + elif isinstance(data, SignedSubsetElement): + self._p = data.positives() + self._n = data.negatives() + self._z = data.zeroes() + + # If we have a tuple, use its information + elif isinstance(data, tuple): + # if we're given vector format + if data[0] in [-1, 0, 1, '+', '0', '-', '']: + if groundset is not None and len(data) != len(groundset): + raise ValueError( + "Length of vector must be same number of elements as ground set") + for i, j in enumerate(data): + label = i + if groundset is not None: + label = groundset[i] + if j == -1 or j == '-': + self._n.add(label) + elif j == 1 or j == '+': + self._p.add(label) + elif j == 0 or j == '' or j == '0': + self._z.add(label) + else: + raise ValueError("Must be tuple of -1, 0, 1") + + # If we have a tuple of tuples + else: + self._p = set(data[0]) + self._n = set(data[1]) + if len(data) > 2: + self._z = set(data[2]) + elif groundset is not None: + self._z = set(groundset).difference( + self._p).difference(self._n) + # If we have a dictionary, use the keys to figure it out + elif isinstance(data, dict): + if 'p' in data: + self._p = data['p'] + if 'positives' in data: + self._p = data['positives'] + if 'n' in data: + self._n = data['n'] + if 'negatives' in data: + self._n = data['negatives'] + if 'z' in data: + self._z = data['z'] + if 'zeroes' in data: + self._z = data['zeroes'] + else: + raise ValueError( + "Either positives and negatives are set or data is a tuple, OrientedMatroidELement or a dict") + + # Type fix + self._p = set(self._p) + self._n = set(self._n) + self._z = set(self._z) + + # Setup the ground set if it's not set yet + if groundset is None: + self._g = list(self._p.union(self._n).union(self._z)) + else: + if not self.support().union(self.zeroes()).issubset(groundset): + raise ValueError("Elements must appear in groundset") + + # Update the zeroes with everything in the ground set + if self._z is None: + self._z = set(groundset).difference(self.support()) + + # ground set should be everything + if not set(groundset).issubset(self.support().union(self.zeroes())): + raise ValueError( + "Every element must be either positive, negative or zero") + self._g = groundset + + self._g = list(self._g) + + Element.__init__(self, parent) + + def __call__(self, var): + """ + Return the sign of an element in the groundset. + """ + + if var in self.positives(): + return 1 + if var in self.negatives(): + return -1 + if var in self.zeroes(): + return 0 + raise ValueError("Not in groundset") + + def __hash__(self): + """ + Return hashed string of signed subset. + """ + fsp = frozenset(self._p) + fsn = frozenset(self._n) + fsz = frozenset(self._z) + return hash((fsp, fsn, fsz)) + + def __neg__(self): + """ + Return the opposite signed subset. + """ + N = copy.copy(self) + N._p = self._n + N._n = self._p + return N + + def __eq__(self, other): + """ + Return whether two elements are equal. + """ + if isinstance(other, SignedSubsetElement): + if self._p == other._p \ + and self._n == other._n \ + and self._z == other._z: + return True + return False + + def __ne__(self, other): + """ + Return whether two elements are not equal. + """ + return not (self == other) + + def _cmp_(self, other): + """ + Arbitrary comparison function so posets work. + """ + if not isinstance(other, SignedSubsetElement): + return 0 + return 1 + # x = len(self.support()) - len(other.support()) + # if x == 0: + # return x + # return x / abs(x) * -1 + + def __bool__(self): + r""" + Returns whether an element is not considered a zero. + + For an oriented matroid, we consider the empty set + `\emptyset = (\emptyset,\emptyset)` to be a zero as + it is the same as the all zero vector. + """ + if len(self.support()) > 0: + return True + return False + + def __iter__(self): + """ + Returns an iter version of self. + """ + for e in self.groundset(): + yield self(e) + + def _repr_(self): + """ + Return a string of the signed subset. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: from oriented_matroids.signed_subset_element import SignedSubsetElement + sage: C = [ ((1,4),(2,3)) , ((2,3),(1,4)) ] + sage: M = OrientedMatroid(C,key='circuit') + sage: SignedSubsetElement(M,data = ((1,4),(2,3))) + +: 1,4 + -: 2,3 + 0: + sage: from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid + sage: AbstractOrientedMatroid.options.display = 'vector' + sage: SignedSubsetElement(M,data = ((1,4),(2,3))) + (1,-1,-1,1) + sage: AbstractOrientedMatroid.options.display = 'set' + + """ + + from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid + if AbstractOrientedMatroid.options.display == 'set': + p = map(str, self.positives()) + n = map(str, self.negatives()) + z = map(str, self.zeroes()) + return "+: " + ','.join(p) + "\n" + \ + "-: " + ','.join(n) + "\n" +\ + "0: " + ','.join(z) + if AbstractOrientedMatroid.options.display == 'vector': + return "(" + ','.join([str(self(e)) for e in self.groundset()]) + ")" + + def _latex_(self): + r""" + Return a latex representation of the signed subset. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: from oriented_matroids.signed_subset_element import SignedSubsetElement + sage: C = [ ((1,4),(2,3)) , ((2,3),(1,4)) ] + sage: M = OrientedMatroid(C,key='circuit') + sage: latex(SignedSubsetElement(M,data = ((1,4),(2,3)))) + \left( \left{1,4\right},\left{2,3\right} \right) + sage: from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid + sage: AbstractOrientedMatroid.options.display = 'vector' + sage: latex(SignedSubsetElement(M,data = ((1,4),(2,3)))) + \left(1,-1,-1,1\right) + + """ + from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid + if AbstractOrientedMatroid.options.display == 'set': + p = map(str, self.positives()) + n = map(str, self.negatives()) + return "\\left( \\left{" + ','.join(p) + \ + "\\right},\\left{" + ','.join(n) + "\\right} \\right)" + if AbstractOrientedMatroid.options.display == 'vector': + ground_set = [str(self(e)) for e in self.groundset()] + return "\\left(" + ','.join(ground_set) + "\\right)" + + def __copy__(self): + """ + Return a copy of the element + """ + return SignedSubsetElement(parent=self.parent(), groundset=self.groundset(), positives=self.positives(), negatives=self.negatives(), zeroes=self.zeroes()) + + def __deepcopy__(self): + """ + Return a copy of the element + """ + return SignedSubsetElement(parent=self.parent(), groundset=self.groundset(), positives=self.positives(), negatives=self.negatives(), zeroes=self.zeroes()) + + def to_list(self): + """ + Convert objcet to a list + """ + return eval("[" + ','.join([str(self(e)) for e in self.groundset()]) + "]") + + def positives(self): + """ + Return the set of positives. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: M = OrientedMatroid([[1,-1,1],[-1,1,-1]], key='circuit') + sage: E = M.elements()[0] + sage: E.positives() + {0, 2} + + """ + return self._p + + def negatives(self): + """ + Return the set of negatives. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: M = OrientedMatroid([[1,-1,1],[-1,1,-1]], key='circuit') + sage: E = M.elements()[0] + sage: E.negatives() + {1} + + """ + return self._n + + def zeroes(self): + r""" + Return the set of zeroes. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') + sage: E = M.elements()[0] + sage: E.zeroes() + {2} + + """ + return self._z + + def support(self): + r""" + Return the support set. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') + sage: E = M.elements()[0] + sage: E.support() + {0, 1} + + """ + return self._p.union(self._n) + + def groundset(self): + r""" + Return the ground set. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: M = OrientedMatroid([[1,-1,0],[-1,1,0]], key='circuit') + sage: E = M.elements()[0] + sage: E.groundset() + [0, 1, 2] + + """ + return self._g + + def composition(self, other): + r""" + Return the composition of two elements. + + The composition of two elements `X` and `Y`, + denoted `X \circ Y` is given componentwise + where for `e \in E` we have `(X \circ Y)(e) = X(e)` + if `X(e) \neq 0` else it equals `Y(e)`. + + EXAMPLES:: + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid + sage: from oriented_matroids.abstract_oriented_matroid import AbstractOrientedMatroid + sage: AbstractOrientedMatroid.options.display='vector' + sage: M = OrientedMatroid([[0],[1],[-1]], key='vector') + sage: E1 = M.elements()[0]; E2 = M.elements()[1] + sage: E1.composition(E2) + (1) + sage: E2.composition(E1) + (1) + sage: E1.composition(E2) == E2.composition(E1) + True + + """ + p = [] + n = [] + z = [] + for e in self.groundset(): + x = self(e) + # If x is non-zero, keep its value + if x == 1: + p.append(e) + elif x == -1: + n.append(e) + else: + # else grab the value of the other + x = other(e) + if x == 1: + p.append(e) + elif x == -1: + n.append(e) + else: + z.append(e) + return type(self)(self.parent(), positives=p, negatives=n, zeroes=z) + + def separation_set(self, other): + r""" + Return the separation set between two elements. + + The separation set of two elements `X` and `Y` + is given by `S(X,Y) = \left\{e \mid X(e) = -Y(e) \neq 0 \right\}` + """ + return self.positives().intersection(other.negatives()).union(self.negatives().intersection(other.positives())) + + def reorientation(self, change_set): + r""" + Return the reorientation by a set. + + The reorientation of `X` by some `A \subseteq E` is + the signed subset (covector) given by `{}_{-A}X` where + `{}_{-A}X^+ = (X^+ \backslash A) \cup (X^- \cap A)` and similarly for + `{}_{-A}X^-`. + """ + if change_set in self.groundset(): + change_set = set([change_set]) + else: + change_set = set(change_set) + + # ensure every elt is in the groundset + for i in change_set: + if i not in self.groundset(): + raise ValueError("{} is not in the ground set".format(i)) + + p = self.positives().difference(change_set).union( + self.negatives().intersection(change_set)) + n = self.negatives().difference(change_set).union( + self.positives().intersection(change_set)) + return type(self)(self.parent(), positives=p, negatives=n, groundset=self.groundset()) + + def is_conformal_with(self, other): + r""" + Return if the two elements are conformal. + + Two elements `X` and `Y` are *conformal* if + `S(X,Y) = \emptyset`. This is true if and only if `X^+ \subseteq Y^+` + and `X^- \subseteq Y^-`. + """ + return len(self.separation_set(other)) == 0 + + def is_restriction_of(self, other): + r""" + Return if `self` is a restriction of `other`. + + A signed subset `X` is a *restriction* of a signed subset `Y` if + `X^+ \subseteq Y^+` and `X^- \subseteq Y^-`. If `X` is a restriction of + `Y` we sometimes say `X` conforms to `Y`. This should not be mistaken + with *is conformal with*. + """ + return self.positives().issubset(other.positives()) \ + and self.negatives().issubset(other.negatives()) + + def is_tope(self): + r""" + Return whether object is a tope. + + A covector is a tope if it is a maximal + element in the face poset. + + .. WARNING:: + + Requires the method `face_lattice` to exist in the oriented + matroid. + """ + if getattr(self.parent(), 'face_lattice', None) is not None: + raise TypeError( + "Topes are only implemented if .face_lattice() is implemented") + + return self in self.parent().topes() + + def is_simplicial(self): + r""" + Return whether or not a tope is simplicial. + + A tope `T` is simplicial if the interval `[0,T]` is boolean + in the face lattice. We note that the breadth of a lattice + can characterize this. In particular a lattice of breadth `n` + contains a sublattice isomorphic to the Boolean lattice of `2^n` + elements. In other words, if `[0,T]` has `2^n` elements and + the breadth of `[0,T]` is `n` then the interval is boolean + and thus `T` is simplicial. + """ + if not self.is_tope(): + raise TypeError("Only topes can be simplicial") + + P = self.parent().face_lattice() + I = P.interval(P.bottom(), self) + PP = P.sublattice(I) + b = PP.breadth() + if len(I) == 2**b: + return True + return False + + def is_zero(self): + """ + Return whether or not element is 0 + """ + return len([1 for e in self.groundset() if self(e) != 0]) == 0 diff --git a/oriented_matroids/vector_oriented_matroid.py b/oriented_matroids/vector_oriented_matroid.py index 1abcca2..ad218c7 100644 --- a/oriented_matroids/vector_oriented_matroid.py +++ b/oriented_matroids/vector_oriented_matroid.py @@ -10,7 +10,7 @@ """ ############################################################################## -# Copyright (C) 2018 Aram Dermenjian +# Copyright (C) 2018 Aram Dermenjian # # Distributed under the terms of the GNU General Public License (GPL) # @@ -48,14 +48,14 @@ class VectorOrientedMatroid(AbstractOrientedMatroid): INPUT: - - ``data`` -- a tuple containing SigneVectorElement elements or data - that can be used to construct :class:`SignedVectorElement` elements + - ``data`` -- a tuple containing SignedSubsetElement elements or data + that can be used to construct :class:`SignedSubsetElement` elements - ``goundset`` -- (default: ``None``) is the groundset for the data. If not provided, we grab the data from the signed subsets. EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: M = OrientedMatroid([[1],[-1],[0]], key='vector'); M Vector oriented matroid of rank 0 sage: M.groundset() @@ -70,7 +70,8 @@ class VectorOrientedMatroid(AbstractOrientedMatroid): .. SEEALSO:: - :class:`oriented_matroids.oriented_matroid.OrientedMatroid` - - :class:`oriented_matroids.oriented_matroids_category.OrientedMatroids` + - :class:`oriented_matroids.abstract_oriented_matroid.AbstractOrientedMatroid` + - :class:`oriented_matroids.signed_subset_element.SignedSubsetElement` """ @staticmethod def __classcall__(cls, data, groundset=None, category=None): @@ -113,11 +114,11 @@ def __init__(self, data, groundset=None, category=None): def is_valid(self): """ - Returns whether our circuits satisfy the circuit axioms. + Return whether our vectors satisfy the vector axioms. EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: V2 = [[1,1]] sage: OrientedMatroid(V2, key='vector') Traceback (most recent call last): @@ -186,7 +187,7 @@ def _repr_(self): EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: V = [[1,1],[-1,-1],[0,0]] sage: M = OrientedMatroid(V, key='vector'); M Vector oriented matroid of rank 1 @@ -198,21 +199,6 @@ def _repr_(self): rep = "Vector oriented matroid" return rep - def circuits(self): - """ - Return the circuits. - - Given a vector oriented matroid, the set of circuits is the set - `Min(V)` which denotes the set of inclusion-minimal (nonempty) signed - subsets. - """ - from sage.combinat.posets.posets import Poset - from oriented_matroids import OrientedMatroid - # remove 0 - vecs = [v for v in self.vectors() if not v.is_zero()] - P = Poset([vecs, lambda x,y: x.is_restriction_of(y)]) - return P.minimal_elements() - def matroid(self): r""" Returns the underlying matroid. @@ -224,18 +210,18 @@ def matroid(self): EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: V = [[1,1],[-1,-1],[0,0]] sage: M = OrientedMatroid(V, key='vector') sage: M.matroid() Matroid of rank 1 on 2 elements with 2 bases """ - circOM = self.to_circuit() + circOM = self.convert_to('circuit') return circOM.matroid() def circuits(self): - """ + r""" Return the circuits. Given a vector oriented matroid, the set of circuits is the set @@ -243,7 +229,8 @@ def circuits(self): subsets. EXAMPLES:: - sage: from oriented_matroids import OrientedMatroid + + sage: from oriented_matroids.oriented_matroid import OrientedMatroid sage: M = OrientedMatroid([[1],[-1],[0]], key='vector') sage: M.circuits() [+: 0 @@ -253,9 +240,11 @@ def circuits(self): -: 0 0: ] """ + if hasattr(self, "_circuits"): + return self._circuits from sage.combinat.posets.posets import Poset - from oriented_matroids import OrientedMatroid # remove 0 vecs = [v for v in self.vectors() if not v.is_zero()] - P = Poset([vecs, lambda x,y: x.is_restriction_of(y)]) - return P.minimal_elements() + P = Poset([vecs, lambda x, y: x.is_restriction_of(y)]) + self._circuits = P.minimal_elements() + return self._circuits diff --git a/setup.py b/setup.py index ad210bd..4c5523d 100644 --- a/setup.py +++ b/setup.py @@ -10,6 +10,7 @@ def readfile(filename): with open(filename, encoding='utf-8') as f: return f.read() + # For the tests class SageTest(TestCommand): def run_tests(self): @@ -26,18 +27,19 @@ def run_tests(self): long_description_content_type='text/markdown', url='https://github.com/thecaligarmo/oriented_matroids', author='Aram Dermenjian', - author_email='aram.dermenjian.math@gmail.com', # choose a main contact email + author_email='aram.dermenjian.math@gmail.com', project_urls={ 'Bug Tracker': 'https://github.com/thecaligarmo/oriented_matroids/issues', }, license='GPLv3+', # This should be consistent with the LICENCE file python_requires='>=3.8', + # classifiers list: https://pypi.python.org/pypi?%3Aaction=list_classifiers classifiers=[ - 'Development Status :: 3 - Alpha', + 'Development Status :: 4 - Beta', 'Intended Audience :: Science/Research', 'Topic :: Scientific/Engineering :: Mathematics', 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', - ], # classifiers list: https://pypi.python.org/pypi?%3Aaction=list_classifiers + ], keywords="SageMath packaging", packages=find_packages(), cmdclass={'test': SageTest}, # adding a special setup command for tests From 69048ea37a6b4299117f331a684a089d9ffedd2e Mon Sep 17 00:00:00 2001 From: Cali Garmo Date: Fri, 9 Feb 2024 12:35:16 +0100 Subject: [PATCH 098/101] Fix exception style --- .gitignore | 3 +++ oriented_matroids/abstract_oriented_matroid.py | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 72364f9..572b044 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,6 @@ ENV/ # Rope project settings .ropeproject + +# vim stuff +*.swp diff --git a/oriented_matroids/abstract_oriented_matroid.py b/oriented_matroids/abstract_oriented_matroid.py index a4dca9a..6c6db3d 100644 --- a/oriented_matroids/abstract_oriented_matroid.py +++ b/oriented_matroids/abstract_oriented_matroid.py @@ -167,9 +167,9 @@ def convert_to(self, new_type=None): if new_type is None: raise TypeError("Must be given a type to convert to") elif new_type in AbstractOrientedMatroid.keys: - try: + if hasattr(self, new_type + 's'): els = getattr(self, new_type + 's')() - except: + else: raise NotImplementedError("No %ss() method found in oriented matroid" % (new_type,)) return OrientedMatroid(els, key=new_type, From 5d822791852a1c63af0facef75e0da864dc8b9d9 Mon Sep 17 00:00:00 2001 From: Cali Garmo Date: Fri, 9 Feb 2024 12:40:24 +0100 Subject: [PATCH 099/101] Add date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dce90b..5752854 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes will be made in this file. -## [0.1.0] - +## [0.1.0] - 2024-02-09 ### Added From 0b3c87cfb5abc41c5f1dff98755c94b10bc0dab7 Mon Sep 17 00:00:00 2001 From: Cali Garmo Date: Fri, 9 Feb 2024 13:03:07 +0100 Subject: [PATCH 100/101] Fix wiki name --- oriented_matroids/oriented_matroid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oriented_matroids/oriented_matroid.py b/oriented_matroids/oriented_matroid.py index 701f4d7..9372a1b 100644 --- a/oriented_matroids/oriented_matroid.py +++ b/oriented_matroids/oriented_matroid.py @@ -10,7 +10,7 @@ many cryptomorphic definitions of oriented matroids. Precise definitions for each type can be found in that classes directory. -See :Wikipedia:`Oriented_matroid` for more details. +See :wikipedia:`Oriented_matroid` for more details. Built-in oriented matroids From 00b28d74ec27c9e8b37aafc1bf1342119dc9e8d5 Mon Sep 17 00:00:00 2001 From: Cali Garmo Date: Fri, 9 Feb 2024 20:40:40 +0100 Subject: [PATCH 101/101] Update README --- README.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ca49c78..5504b6a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This package contains an oriented matroid implementation for sagemath. ## Current version -The current version is 0.1.0 and is compatible with sagemath 10.0. It is in beta and is open for testing from others. +The current version is 0.1.0 and is compatible/has been tested with sagemath 10.0, 10.1 and 10.2. It is in beta and is open for testing from others. **NOTE:** This package will be integrating into SageMath directly. If you see any errors while using this please, open an issue and let us know so we can correct it. @@ -15,7 +15,7 @@ The current version is 0.1.0 and is compatible with sagemath 10.0. It is in beta Use `pip` to install the package: ``` -$ sage -pip install --index-url https://test.pypi.org/simple/ --no-deps oriented_matroids +$ sage -pip install oriented_matroids ``` ### Local install from source @@ -29,17 +29,17 @@ Change to the root directory and run: $ sage -pip install . ``` -For convenience this package contains a makefile with this and other often used commands. Should you wish too, you can use the shorthand: +For convenience this package contains a makefile with this and other often used commands. This file neds updating to your sage installation directory before running. ``` $ make install ``` -Note that you might need to alter the make file in order for this to run properly if your sage is located in another directory. - ### Common errors -If you get "SSL" errors, try the fixes found on: [ask sagemath](https://ask.sagemath.org/question/51130/ssl-error-using-sage-pip-install-to-download-a-package/) +1. If you get "SSL" errors, try the fixes found on: [ask sagemath](https://ask.sagemath.org/question/51130/ssl-error-using-sage-pip-install-to-download-a-package/) +2. If `make` didn't work, make sure you updated where your sage directory is in the make file. + ## Using the package after install After install, you can start sage and run the following command to have all methods available: @@ -57,3 +57,11 @@ Alternatively, if you installed locally and want to uninstall using `make`, you ``` $ make uninstall ``` + +## Documentation +To make the documentation, you can use `make`: +``` +$ make doc +``` + +To refresh the doc, I would recommend first cleaning it using `make clean` before running `make doc` again, just in case.