conda / conda-libmamba-solver

The libmamba based solver for conda.
https://conda.github.io/conda-libmamba-solver/
Other
196 stars 24 forks source link

Non-deterministic solve #75

Closed maximlt closed 1 year ago

maximlt commented 1 year ago

Checklist

What happened?

The same command - installing python=3.8 bokeh>=1.0 holoviews>=1.1.0 in a new environment - ends up installing different package versions. I'd expect the solve the provide the same output, given the same input?

Here's a script to reproduce that:

import re
import subprocess

cmd = 'conda create --experimental-solver libmamba -n testtesttest -c conda-forge --override-channels python=3.8 "bokeh>=1.0" "holoviews>=1.1.0" --dry-run --offline'
pattern = r'\/(.+)::bokeh-(\d+.\d+.\d+)'

for _ in range(10):
    result = subprocess.run(cmd.split(' '), capture_output=True, text=True)
    print(re.findall(pattern, result.stdout))

Output:

[('osx-64', '2.4.3')]
[('noarch', '3.0.2')]
[('noarch', '3.0.2')]
[('noarch', '3.0.2')]
[('osx-64', '2.4.3')]
[('noarch', '3.0.2')]
[('osx-64', '2.4.3')]
[('noarch', '3.0.2')]
[('osx-64', '2.4.3')]
[('noarch', '3.0.2')]

The output shows that conda may install Bokeh 2.4.3 or 3.0.2. This is not the only version that changes but I chose to highlight just one to reveal what I think is the issue, i.e. that the same command could lead to different environments.

(The latest conda-forge HoloViews version - 1.15.2 - pins Bokeh to <3)

Conda Info

active environment : None
            shell level : 0
       user config file : /Users/mliquet/.condarc
 populated config files : /Users/mliquet/.condarc
          conda version : 22.9.0
    conda-build version : not installed
         python version : 3.9.5.final.0
       virtual packages : __osx=10.16=0
                          __unix=0=0
                          __archspec=1=x86_64
       base environment : /Users/mliquet/miniconda3  (writable)
      conda av data dir : /Users/mliquet/miniconda3/etc/conda
  conda av metadata url : None
           channel URLs : https://repo.anaconda.com/pkgs/main/osx-64
                          https://repo.anaconda.com/pkgs/main/noarch
                          https://repo.anaconda.com/pkgs/r/osx-64
                          https://repo.anaconda.com/pkgs/r/noarch
          package cache : /Users/mliquet/miniconda3/pkgs
                          /Users/mliquet/.conda/pkgs
       envs directories : /Users/mliquet/miniconda3/envs
                          /Users/mliquet/.conda/envs
               platform : osx-64
             user-agent : conda/22.9.0 requests/2.27.1 CPython/3.9.5 Darwin/21.4.0 OSX/10.16
                UID:GID : 502:20
             netrc file : None
           offline mode : False

Conda Config

No response

Conda list

# packages in environment at /Users/mliquet/miniconda3:
#
# Name                    Version                   Build  Channel
brotlipy                  0.7.0           py39h9ed2024_1003    defaults
bzip2                     1.0.8                h1de35cc_0    defaults
c-ares                    1.18.1               hca72f7f_0    defaults
ca-certificates           2022.10.11           hecd8cb5_0    defaults
certifi                   2022.9.24        py39hecd8cb5_0    defaults
cffi                      1.15.1           py39hc55c11b_0    defaults
charset-normalizer        2.0.4              pyhd3eb1b0_0    defaults
colorama                  0.4.5            py39hecd8cb5_0    defaults
conda                     22.9.0           py39hecd8cb5_0    defaults
conda-libmamba-solver     22.8.1           py39hecd8cb5_0    defaults
conda-package-handling    1.9.0            py39hca72f7f_1    defaults
cryptography              38.0.1           py39hf6deb26_0    defaults
icu                       58.2                 h0a44026_3    defaults
idna                      3.4              py39hecd8cb5_0    defaults
importlib-metadata        4.11.3           py39hecd8cb5_0    defaults
importlib_metadata        4.11.3               hd3eb1b0_0    defaults
krb5                      1.19.2               hcd88c3b_0    defaults
libarchive                3.5.2                ha0e9c3a_0    defaults
libcurl                   7.85.0               h6dfd666_0    defaults
libcxx                    14.0.6               h9765a3e_0    defaults
libedit                   3.1.20210910         hca72f7f_0    defaults
libev                     4.33                 h9ed2024_1    defaults
libffi                    3.3                  hb1e8313_2    defaults
libiconv                  1.16                 hca72f7f_2    defaults
libmamba                  0.24.0               hf1b0957_0    defaults
libmambapy                0.24.0           py39haf03e11_0    defaults
libnghttp2                1.46.0               ha29bfda_0    defaults
libsolv                   0.7.22               h8346a28_0    defaults
libssh2                   1.10.0               h0a4fc7d_0    defaults
libxml2                   2.9.14               hbf8cd5e_0    defaults
lz4-c                     1.9.3                h23ab428_1    defaults
ncurses                   6.3                  hca72f7f_3    defaults
openssl                   1.1.1s               hca72f7f_0    defaults
pcre2                     10.37                he7042d7_1    defaults
pycosat                   0.6.4            py39hca72f7f_0    defaults
pycparser                 2.21               pyhd3eb1b0_0    defaults
pyopenssl                 22.0.0             pyhd3eb1b0_0    defaults
pysocks                   1.7.1            py39hecd8cb5_0    defaults
python                    3.9.5                h88f2d9e_3    defaults
python.app                3                py39h9ed2024_0    defaults
readline                  8.2                  hca72f7f_0    defaults
reproc                    14.2.4               he9d5cce_1    defaults
reproc-cpp                14.2.4               he9d5cce_1    defaults
requests                  2.27.1             pyhd3eb1b0_0    defaults
ruamel_yaml               0.15.100         py39h9ed2024_0    defaults
setuptools                58.0.4           py39hecd8cb5_0    defaults
sqlite                    3.39.3               h707629a_0    defaults
tk                        8.6.12               h5d9f67b_0    defaults
toolz                     0.12.0           py39hecd8cb5_0    defaults
tqdm                      4.63.0             pyhd3eb1b0_0    defaults
tzdata                    2022f                h04d1e81_0    defaults
urllib3                   1.26.12          py39hecd8cb5_0    defaults
xz                        5.2.6                hca72f7f_0    defaults
yaml                      0.2.5                haf1e3a3_0    defaults
yaml-cpp                  0.7.0                he9d5cce_1    defaults
zipp                      3.8.0            py39hecd8cb5_0    defaults
zlib                      1.2.13               h4dc903c_0    defaults
zstd                      1.5.2                hcb37349_0    defaults

Additional Context

No response

skupr-anaconda commented 1 year ago

holoviews-1.14.9 pyhd8ed1ab_0 is installing with bokeh-3.0.2 pyhd8ed1ab_0 holoviews-1.15.2 pyhd8ed1ab_0 is installing with bokeh-2.4.3 pyhd8ed1ab_3 Both results because the recipe was updated for v1.15.2 https://github.com/conda-forge/holoviews-feedstock/commit/0d10f2159bdfd618b984b26bb69e87963ea43eb0 But the correct one should be holoviews-1.15.2 pyhd8ed1ab_0 installing with bokeh-2.4.3 pyhd8ed1ab_3

maximlt commented 1 year ago

But the correct one should be holoviews-1.15.2 pyhd8ed1ab_0 installs with bokeh-2.4.3 pyhd8ed1ab_3

I'm not sure that there is a "correct" one, both are valid solutions. What I'd expect is conda to always return the same solution :) (But yes I prefer the solution you suggest as the other one needs to install a pretty old version of Panel (a dependency of HoloViews) that didn't have any upper pin for Bokeh.)

jezdez commented 1 year ago

@maximlt I'm just acknowledging that @jaimergp and me have seen and discussed this briefly before he left for PTO and that it was not enough time to work on before the currently being prepared conda release happened. Appreciate the filing, though!

jaimergp commented 1 year ago

I cannot reproduce this on linux-64 or osx-64 (using CONDA_SUBDIR appropiately). Maybe because of https://github.com/conda-forge/conda-forge-repodata-patches-feedstock/pull/357 we don't have the necessary packaging landscape?

This is what I get:

$ python determinism.py 
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
maximlt commented 1 year ago

Yes certainly. Do you know if there's a way to download a repodata.json file that dates from before that patch?

jaimergp commented 1 year ago

Technically we can:

  1. Get the unpatched repodata from <channel>/<subdir>/repodata_from_packages.json.
  2. Parse and remove entries with timestamp >= wanted date.
  3. Get the repodata patches repo and rollback in the git history to the wanted date
  4. Run the patches and put the result file in a mockup local channel.

However I tried the unpatched repodata directly (with --repodata-fn repodata_from_packages.json) and it gave the same results. So unless it's the patching that introduce the multi-solve problem, then I don't know if we can reproduce.

hoxbro commented 1 year ago

Try to set holoviews==1.15.2. Holoviews 1.15.3 have put a lower pin on panel.

hoxbro commented 1 year ago

I can still get a non-deterministic solution with the following code, but only for conda+libmamba. When running mamba, I get a deterministic solution.

import re
import subprocess

cmd = 'conda create --experimental-solver libmamba -n testtesttest -c conda-forge --override-channels python=3.8 bokeh hvplot --dry-run --offline'
pattern = r'\/(.+)::bokeh-(\d+.\d+.\d+)'

for _ in range(10):
    result = subprocess.run(cmd.split(' '), capture_output=True, text=True)
    print(re.findall(pattern, result.stdout))

cmd = 'mamba create -n testtesttest -c conda-forge --override-channels python=3.8 bokeh hvplot --dry-run --offline'
pattern = r"bokeh\s+(\d+.\d+.\d+).+?conda-forge\/(.+?)\s"

for _ in range(10):
    result = subprocess.run(cmd.split(' '), capture_output=True, text=True)
    print(re.findall(pattern, result.stdout))

Conda output

[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '2.4.3')]
[('noarch', '3.0.3')]
[('noarch', '2.4.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]

Mamba output

[('3.0.3', 'noarch')]
[('3.0.3', 'noarch')]
[('3.0.3', 'noarch')]
[('3.0.3', 'noarch')]
[('3.0.3', 'noarch')]
[('3.0.3', 'noarch')]
[('3.0.3', 'noarch')]
[('3.0.3', 'noarch')]
[('3.0.3', 'noarch')]
[('3.0.3', 'noarch')]
hoxbro commented 1 year ago

I noticed that if I swap the order of hvplot and bokeh and use this command: mamba create -n testtesttest -c conda-forge --override-channels python=3.8 hvplot bokeh --dry-run --offline.

The output for mamba is still non-deterministic, but the solve gives bokeh=2.4.3. So maybe some sorting of the packages is done by mamba but not with conda+libmamba.

jaimergp commented 1 year ago

This is excellent @Hoxbro, now I can look into this and see where the non-determinism is coming from. Thank you so much!

jaimergp commented 1 year ago

I still get deterministic results:

python -I determinism.py 
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]

Maybe it's a version-dependent thing? My base environment contains:

conda                     22.11.1          <dev>  # from current main
conda-libmamba-solver     22.12.0          <dev>  # from current main
libmamba                  1.0.0                ha06983f_0  defaults
libmambapy                1.0.0            py39ha06983f_0  defaults
libsolv                   0.7.22               he621ea3_0  defaults

We haven't done much work on the solver input side lately so I don't think the dev versions have much to do. Can you report your version and channels?

hoxbro commented 1 year ago

My base environment:

conda                     22.11.1         py310hff52083_1    conda-forge
conda-libmamba-solver     22.12.0            pyhd8ed1ab_0    conda-forge
libmamba                  1.1.0                hde2b089_3    conda-forge
libmambapy                1.1.0           py310h1428755_3    conda-forge
libsolv                   0.7.23               h3eb15da_0    conda-forge
conda info ``` active environment : base active env location : /home/shh/miniconda3 shell level : 1 user config file : /home/shh/.condarc populated config files : /home/shh/miniconda3/.condarc /home/shh/.condarc conda version : 22.11.1 conda-build version : 3.23.3 python version : 3.10.8.final.0 virtual packages : __archspec=1=x86_64 __glibc=2.35=0 __linux=6.0.12=0 __unix=0=0 base environment : /home/shh/miniconda3 (writable) conda av data dir : /home/shh/miniconda3/etc/conda conda av metadata url : None channel URLs : https://conda.anaconda.org/conda-forge/linux-64 https://conda.anaconda.org/conda-forge/noarch package cache : /home/shh/miniconda3/pkgs /home/shh/.conda/pkgs envs directories : /home/shh/miniconda3/envs /home/shh/.conda/envs platform : linux-64 user-agent : conda/22.11.1 requests/2.28.1 CPython/3.10.8 Linux/6.0.12-76060006-generic pop/22.04 glibc/2.35 UID:GID : 1000:1000 netrc file : None offline mode : False ```
conda list ``` # packages in environment at /home/shh/miniconda3: # # Name Version Build Channel _ipython_minor_entry_point 8.7.0 hb6b4a82_0 conda-forge _libgcc_mutex 0.1 conda_forge conda-forge _openmp_mutex 4.5 2_gnu conda-forge alsa-lib 1.2.8 h166bdaf_0 conda-forge anyio 3.6.2 pyhd8ed1ab_0 conda-forge argon2-cffi 21.3.0 pyhd8ed1ab_0 conda-forge argon2-cffi-bindings 21.2.0 py310h5764c6d_3 conda-forge asttokens 2.2.1 pyhd8ed1ab_0 conda-forge attr 2.5.1 h166bdaf_1 conda-forge attrs 22.2.0 pyh71513ae_0 conda-forge babel 2.11.0 pyhd8ed1ab_0 conda-forge backcall 0.2.0 pyh9f0ad1d_0 conda-forge backports 1.0 pyhd8ed1ab_3 conda-forge backports.functools_lru_cache 1.6.4 pyhd8ed1ab_0 conda-forge beautifulsoup4 4.11.1 pyha770c72_0 conda-forge black 22.10.0 py310hff52083_2 conda-forge bleach 5.0.1 pyhd8ed1ab_0 conda-forge bokeh 2.4.3 pyhd8ed1ab_3 conda-forge brotli 1.0.9 h166bdaf_8 conda-forge brotli-bin 1.0.9 h166bdaf_8 conda-forge brotli-python 1.0.9 py310hd8f1fbe_8 conda-forge brotlicffi 1.0.9.2 py310hd8f1fbe_3 conda-forge brotlipy 0.7.0 py310h5764c6d_1005 conda-forge bs4 4.11.1 hd8ed1ab_0 conda-forge bzip2 1.0.8 h7f98852_4 conda-forge c-ares 1.18.1 h7f98852_0 conda-forge ca-certificates 2022.12.7 ha878542_0 conda-forge certifi 2022.12.7 pyhd8ed1ab_0 conda-forge cffi 1.15.1 py310h255011f_3 conda-forge chardet 5.1.0 py310hff52083_0 conda-forge charset-normalizer 2.1.1 pyhd8ed1ab_0 conda-forge click 8.1.3 unix_pyhd8ed1ab_2 conda-forge colorama 0.4.6 pyhd8ed1ab_0 conda-forge comm 0.1.2 pyhd8ed1ab_0 conda-forge commonmark 0.9.1 py_0 conda-forge conda 22.11.1 py310hff52083_1 conda-forge conda-build 3.23.3 py310hff52083_0 conda-forge conda-libmamba-solver 22.12.0 pyhd8ed1ab_0 conda-forge conda-package-handling 2.0.2 pyh38be061_0 conda-forge conda-package-streaming 0.7.0 pyhd8ed1ab_1 conda-forge contourpy 1.0.6 py310hbf28c38_0 conda-forge cryptography 38.0.4 py310h600f1e7_0 conda-forge cycler 0.11.0 pyhd8ed1ab_0 conda-forge dataclasses 0.8 pyhc8e2a94_3 conda-forge dbus 1.13.6 h5008d03_3 conda-forge debugpy 1.6.4 py310hd8f1fbe_0 conda-forge decorator 5.1.1 pyhd8ed1ab_0 conda-forge defusedxml 0.7.1 pyhd8ed1ab_0 conda-forge entrypoints 0.4 pyhd8ed1ab_0 conda-forge et_xmlfile 1.0.1 py_1001 conda-forge executing 1.2.0 pyhd8ed1ab_0 conda-forge expat 2.5.0 h27087fc_0 conda-forge fftw 3.3.10 nompi_hf0379b8_106 conda-forge filelock 3.8.2 pyhd8ed1ab_0 conda-forge flake8 6.0.0 pyhd8ed1ab_0 conda-forge flit-core 3.8.0 pyhd8ed1ab_0 conda-forge fmt 9.1.0 h924138e_0 conda-forge font-ttf-dejavu-sans-mono 2.37 hab24e00_0 conda-forge font-ttf-inconsolata 3.000 h77eed37_0 conda-forge font-ttf-source-code-pro 2.038 h77eed37_0 conda-forge font-ttf-ubuntu 0.83 hab24e00_0 conda-forge fontconfig 2.14.1 hc2a2eb6_0 conda-forge fonts-conda-ecosystem 1 0 conda-forge fonts-conda-forge 1 0 conda-forge fonttools 4.38.0 py310h5764c6d_1 conda-forge freetype 2.12.1 hca18f0e_1 conda-forge future 0.18.2 pyhd8ed1ab_6 conda-forge gettext 0.21.1 h27087fc_0 conda-forge giflib 5.2.1 h36c2ea0_2 conda-forge glib 2.74.1 h6239696_1 conda-forge glib-tools 2.74.1 h6239696_1 conda-forge glob2 0.7 py_0 conda-forge gmp 6.2.1 h58526e2_0 conda-forge gst-plugins-base 1.21.3 h4243ec0_1 conda-forge gstreamer 1.21.3 h25f0c4b_1 conda-forge gstreamer-orc 0.4.33 h166bdaf_0 conda-forge icu 70.1 h27087fc_0 conda-forge idna 3.4 pyhd8ed1ab_0 conda-forge importlib-metadata 5.2.0 pyha770c72_0 conda-forge importlib_metadata 5.2.0 hd8ed1ab_0 conda-forge importlib_resources 5.10.1 pyhd8ed1ab_1 conda-forge ipykernel 6.19.4 pyh210e3f2_0 conda-forge ipython 8.7.0 pyh41d4057_0 conda-forge ipython_genutils 0.2.0 py_1 conda-forge isort 5.11.4 pyhd8ed1ab_0 conda-forge jack 1.9.21 h583fa2b_2 conda-forge jedi 0.18.2 pyhd8ed1ab_0 conda-forge jinja2 3.1.2 pyhd8ed1ab_1 conda-forge jpeg 9e h166bdaf_2 conda-forge json5 0.9.5 pyh9f0ad1d_0 conda-forge jsonschema 4.17.3 pyhd8ed1ab_0 conda-forge jupyter_client 7.4.8 pyhd8ed1ab_0 conda-forge jupyter_core 5.1.0 py310hff52083_0 conda-forge jupyter_events 0.5.0 pyhd8ed1ab_1 conda-forge jupyter_server 2.0.5 pyhd8ed1ab_0 conda-forge jupyter_server_terminals 0.4.3 pyhd8ed1ab_0 conda-forge jupyterlab 3.5.2 pyhd8ed1ab_0 conda-forge jupyterlab_code_formatter 1.5.3 pyhd8ed1ab_0 conda-forge jupyterlab_pygments 0.2.2 pyhd8ed1ab_0 conda-forge jupyterlab_server 2.16.6 pyhd8ed1ab_0 conda-forge keyutils 1.6.1 h166bdaf_0 conda-forge kiwisolver 1.4.4 py310hbf28c38_1 conda-forge krb5 1.20.1 h81ceb04_0 conda-forge lame 3.100 h166bdaf_1003 conda-forge lcms2 2.14 hfd0df8a_1 conda-forge ld_impl_linux-64 2.39 hcc3a1bd_1 conda-forge lerc 4.0.0 h27087fc_0 conda-forge libarchive 3.6.2 h3d51595_0 conda-forge libblas 3.9.0 16_linux64_openblas conda-forge libbrotlicommon 1.0.9 h166bdaf_8 conda-forge libbrotlidec 1.0.9 h166bdaf_8 conda-forge libbrotlienc 1.0.9 h166bdaf_8 conda-forge libcap 2.66 ha37c62d_0 conda-forge libcblas 3.9.0 16_linux64_openblas conda-forge libclang 15.0.6 default_h2e3cab8_0 conda-forge libclang13 15.0.6 default_h3a83d3e_0 conda-forge libcups 2.3.3 h36d4200_3 conda-forge libcurl 7.87.0 hdc1c0ab_0 conda-forge libdb 6.2.32 h9c3ff4c_0 conda-forge libdeflate 1.14 h166bdaf_0 conda-forge libedit 3.1.20191231 he28a2e2_2 conda-forge libev 4.33 h516909a_1 conda-forge libevent 2.1.10 h28343ad_4 conda-forge libffi 3.4.2 h7f98852_5 conda-forge libflac 1.4.2 h27087fc_0 conda-forge libgcc-ng 12.2.0 h65d4601_19 conda-forge libgcrypt 1.10.1 h166bdaf_0 conda-forge libgfortran-ng 12.2.0 h69a702a_19 conda-forge libgfortran5 12.2.0 h337968e_19 conda-forge libglib 2.74.1 h606061b_1 conda-forge libgomp 12.2.0 h65d4601_19 conda-forge libgpg-error 1.45 hc0c96e0_0 conda-forge libiconv 1.17 h166bdaf_0 conda-forge liblapack 3.9.0 16_linux64_openblas conda-forge liblief 0.12.3 h27087fc_0 conda-forge libllvm14 14.0.6 he0ac6c6_1 conda-forge libllvm15 15.0.6 h63197d8_0 conda-forge libmamba 1.1.0 hde2b089_3 conda-forge libmambapy 1.1.0 py310h1428755_3 conda-forge libnghttp2 1.47.0 hff17c54_1 conda-forge libnsl 2.0.0 h7f98852_0 conda-forge libogg 1.3.4 h7f98852_1 conda-forge libopenblas 0.3.21 pthreads_h78a6416_3 conda-forge libopus 1.3.1 h7f98852_1 conda-forge libpng 1.6.39 h753d276_0 conda-forge libpq 15.1 hb675445_2 conda-forge libsndfile 1.1.0 hcb278e6_1 conda-forge libsodium 1.0.18 h36c2ea0_1 conda-forge libsolv 0.7.23 h3eb15da_0 conda-forge libsqlite 3.40.0 h753d276_0 conda-forge libssh2 1.10.0 hf14f497_3 conda-forge libstdcxx-ng 12.2.0 h46fd767_19 conda-forge libsystemd0 252 h2a991cd_0 conda-forge libtiff 4.5.0 h82bc61c_0 conda-forge libtool 2.4.6 h9c3ff4c_1008 conda-forge libudev1 252 h166bdaf_0 conda-forge libuuid 2.32.1 h7f98852_1000 conda-forge libuv 1.44.2 h166bdaf_0 conda-forge libvorbis 1.3.7 h9c3ff4c_0 conda-forge libwebp 1.2.4 h1daa5a0_1 conda-forge libwebp-base 1.2.4 h166bdaf_0 conda-forge libxcb 1.13 h7f98852_1004 conda-forge libxkbcommon 1.0.3 he3ba5ed_0 conda-forge libxml2 2.10.3 h7463322_0 conda-forge libxslt 1.1.37 h873f0b0_0 conda-forge libzlib 1.2.13 h166bdaf_4 conda-forge lxml 4.9.2 py310hbdc0903_0 conda-forge lz4-c 1.9.3 h9c3ff4c_1 conda-forge lzo 2.10 h516909a_1000 conda-forge mamba 1.1.0 py310h51d5547_3 conda-forge markdown 3.4.1 pyhd8ed1ab_0 conda-forge markupsafe 2.1.1 py310h5764c6d_2 conda-forge matplotlib 3.6.2 py310hff52083_0 conda-forge matplotlib-base 3.6.2 py310h8d5ebf3_0 conda-forge matplotlib-inline 0.1.6 pyhd8ed1ab_0 conda-forge maturin 0.14.7 py310h4426083_0 conda-forge mccabe 0.7.0 pyhd8ed1ab_0 conda-forge mistune 2.0.4 pyhd8ed1ab_0 conda-forge mpg123 1.31.1 h27087fc_0 conda-forge munkres 1.1.4 pyh9f0ad1d_0 conda-forge mutagen 1.46.0 pyhd8ed1ab_0 conda-forge mypy 0.991 py310h5764c6d_0 conda-forge mypy_extensions 0.4.3 py310hff52083_6 conda-forge mysql-common 8.0.31 h26416b9_0 conda-forge mysql-libs 8.0.31 hbc51c84_0 conda-forge nb_conda_kernels 2.3.1 py310hff52083_2 conda-forge nbclassic 0.4.8 pyhd8ed1ab_0 conda-forge nbclient 0.7.2 pyhd8ed1ab_0 conda-forge nbconvert 7.2.7 pyhd8ed1ab_0 conda-forge nbconvert-core 7.2.7 pyhd8ed1ab_0 conda-forge nbconvert-pandoc 7.2.7 pyhd8ed1ab_0 conda-forge nbformat 5.7.1 pyhd8ed1ab_0 conda-forge ncurses 6.3 h27087fc_1 conda-forge nest-asyncio 1.5.6 pyhd8ed1ab_0 conda-forge nodejs 18.12.1 h8839609_0 conda-forge notebook 6.5.2 pyha770c72_1 conda-forge notebook-shim 0.2.2 pyhd8ed1ab_0 conda-forge nspr 4.35 h27087fc_0 conda-forge nss 3.82 he02c5a1_0 conda-forge numpy 1.24.0 py310h08bbf29_0 conda-forge odfpy 1.4.1 py_0 conda-forge openjpeg 2.5.0 hfec8fc6_2 conda-forge openpyxl 3.0.10 py310h5764c6d_2 conda-forge openssl 3.0.7 h0b41bf4_1 conda-forge packaging 22.0 pyhd8ed1ab_0 conda-forge pandas 1.5.2 py310h769672d_0 conda-forge pandoc 2.19.2 h32600fe_1 conda-forge pandocfilters 1.5.0 pyhd8ed1ab_0 conda-forge panel 0.14.2 pyhd8ed1ab_0 conda-forge param 1.12.3 pyh1a96a4e_0 conda-forge parso 0.8.3 pyhd8ed1ab_0 conda-forge patch 2.7.6 h7f98852_1002 conda-forge patchelf 0.17.0 h58526e2_0 conda-forge pathspec 0.10.3 pyhd8ed1ab_0 conda-forge pcre 8.45 h9c3ff4c_0 conda-forge pcre2 10.40 hc3806b6_0 conda-forge pexpect 4.8.0 pyh9f0ad1d_2 conda-forge pickleshare 0.7.5 py_1003 conda-forge pillow 9.2.0 py310h023d228_4 conda-forge pip 22.3.1 pyhd8ed1ab_0 conda-forge pkginfo 1.9.2 pyhd8ed1ab_0 conda-forge pkgutil-resolve-name 1.3.10 pyhd8ed1ab_0 conda-forge platformdirs 2.6.0 pyhd8ed1ab_0 conda-forge pluggy 1.0.0 pyhd8ed1ab_5 conda-forge ply 3.11 py_1 conda-forge portaudio 19.6.0 h583fa2b_7 conda-forge prometheus_client 0.15.0 pyhd8ed1ab_0 conda-forge prompt-toolkit 3.0.36 pyha770c72_0 conda-forge psutil 5.9.4 py310h5764c6d_0 conda-forge pthread-stubs 0.4 h36c2ea0_1001 conda-forge ptyprocess 0.7.0 pyhd3deb0d_0 conda-forge pulseaudio 16.1 h126f2b6_0 conda-forge pure_eval 0.2.2 pyhd8ed1ab_0 conda-forge py-lief 0.12.3 py310hd8f1fbe_0 conda-forge pybind11-abi 4 hd8ed1ab_3 conda-forge pycodestyle 2.10.0 pyhd8ed1ab_0 conda-forge pycosat 0.6.4 py310h5764c6d_1 conda-forge pycparser 2.21 pyhd8ed1ab_0 conda-forge pycryptodomex 3.16.0 py310h5764c6d_0 conda-forge pyct 0.4.6 py_0 conda-forge pyct-core 0.4.6 py_0 conda-forge pyflakes 3.0.1 pyhd8ed1ab_0 conda-forge pygments 2.13.0 pyhd8ed1ab_0 conda-forge pyopenssl 22.1.0 pyhd8ed1ab_0 conda-forge pyparsing 3.0.9 pyhd8ed1ab_0 conda-forge pyqt 5.15.7 py310h29803b5_2 conda-forge pyqt5-sip 12.11.0 py310hd8f1fbe_2 conda-forge pyrsistent 0.19.2 py310h5764c6d_0 conda-forge pysocks 1.7.1 pyha2e5f31_6 conda-forge python 3.10.8 h4a9ceb5_0_cpython conda-forge python-dateutil 2.8.2 pyhd8ed1ab_0 conda-forge python-fastjsonschema 2.16.2 pyhd8ed1ab_0 conda-forge python-json-logger 2.0.4 pyhd8ed1ab_0 conda-forge python-libarchive-c 4.0 py310hff52083_2 conda-forge python_abi 3.10 3_cp310 conda-forge pytz 2022.7 pyhd8ed1ab_0 conda-forge pyviz_comms 2.2.1 pyhd8ed1ab_1 conda-forge pyyaml 6.0 py310h5764c6d_5 conda-forge pyzmq 24.0.1 py310h330234f_1 conda-forge qt-main 5.15.6 hf6cd601_5 conda-forge readline 8.1.2 h0f457ee_0 conda-forge reproc 14.2.4 h0b41bf4_0 conda-forge reproc-cpp 14.2.4 hcb278e6_0 conda-forge requests 2.28.1 pyhd8ed1ab_1 conda-forge rich 12.6.0 pyhd8ed1ab_0 conda-forge ripgrep 13.0.0 h2f28480_2 conda-forge ruamel.yaml 0.17.21 py310h5764c6d_2 conda-forge ruamel.yaml.clib 0.2.7 py310h1fa729e_1 conda-forge ruamel_yaml 0.15.80 py310h5764c6d_1008 conda-forge scipy 1.9.3 py310hdfbd76f_2 conda-forge send2trash 1.8.0 pyhd8ed1ab_0 conda-forge setuptools 65.6.3 pyhd8ed1ab_0 conda-forge sip 6.7.5 py310hd8f1fbe_0 conda-forge six 1.16.0 pyh6c4a22f_0 conda-forge sniffio 1.3.0 pyhd8ed1ab_0 conda-forge soupsieve 2.3.2.post1 pyhd8ed1ab_0 conda-forge sqlite 3.40.0 h4ff8645_0 conda-forge stack_data 0.6.2 pyhd8ed1ab_0 conda-forge terminado 0.17.1 pyh41d4057_0 conda-forge tinycss2 1.2.1 pyhd8ed1ab_0 conda-forge tk 8.6.12 h27826a3_0 conda-forge toml 0.10.2 pyhd8ed1ab_0 conda-forge tomli 2.0.1 pyhd8ed1ab_0 conda-forge toolz 0.12.0 pyhd8ed1ab_0 conda-forge tornado 6.2 py310h5764c6d_1 conda-forge tqdm 4.64.1 pyhd8ed1ab_0 conda-forge traitlets 5.8.0 pyhd8ed1ab_0 conda-forge typed-ast 1.5.4 py310h5764c6d_1 conda-forge typing_extensions 4.4.0 pyha770c72_0 conda-forge tzdata 2022g h191b570_0 conda-forge unicodedata2 15.0.0 py310h5764c6d_0 conda-forge urllib3 1.26.13 pyhd8ed1ab_0 conda-forge wcwidth 0.2.5 pyh9f0ad1d_2 conda-forge webencodings 0.5.1 py_1 conda-forge websocket-client 1.4.2 pyhd8ed1ab_0 conda-forge websockets 10.4 py310h5764c6d_1 conda-forge wheel 0.38.4 pyhd8ed1ab_0 conda-forge xcb-util 0.4.0 h166bdaf_0 conda-forge xcb-util-image 0.4.0 h166bdaf_0 conda-forge xcb-util-keysyms 0.4.0 h166bdaf_0 conda-forge xcb-util-renderutil 0.3.9 h166bdaf_0 conda-forge xcb-util-wm 0.4.1 h166bdaf_0 conda-forge xorg-libxau 1.0.9 h7f98852_0 conda-forge xorg-libxdmcp 1.1.3 h7f98852_0 conda-forge xz 5.2.6 h166bdaf_0 conda-forge yaml 0.2.5 h7f98852_2 conda-forge yaml-cpp 0.7.0 h27087fc_2 conda-forge yt-dlp 2022.11.11 pyhd8ed1ab_1 conda-forge zeromq 4.3.4 h9c3ff4c_1 conda-forge zipp 3.11.0 pyhd8ed1ab_0 conda-forge zlib 1.2.13 h166bdaf_4 conda-forge zstandard 0.19.0 py310hdeb6495_1 conda-forge zstd 1.5.2 h8a70e8d_4 conda-forge ```
cat ~/.condarc ``` ssl_verify: true changeps1: false channel_priority: strict channels: - conda-forge ```
costrouc commented 1 year ago

Hey @maximlt I'm going to work on investigating this issue. Thanks for the detailed information and @Hoxbro appreciate the example to reproduce this issue :smile:

costrouc commented 1 year ago

To reproduce I have run the steps in https://github.com/conda/conda-libmamba-solver/blob/main/docs/dev/setup.md using the docker container.

conda info (slightly different for each version I tried) ````
     active environment : base
    active env location : /opt/conda
            shell level : 1
       user config file : /home/test_user/.condarc
 populated config files : 
          conda version : 23.1.0
    conda-build version : 3.23.3
         python version : 3.9.15.final.0
       virtual packages : __archspec=1=x86_64
                          __glibc=2.31=0
                          __linux=6.0.7=0
                          __unix=0=0
       base environment : /opt/conda  (read only)
      conda av data dir : /opt/conda/etc/conda
  conda av metadata url : None
           channel URLs : https://repo.anaconda.com/pkgs/main/linux-64
                          https://repo.anaconda.com/pkgs/main/noarch
                          https://repo.anaconda.com/pkgs/r/linux-64
                          https://repo.anaconda.com/pkgs/r/noarch
          package cache : /opt/conda/pkgs
                          /home/test_user/.conda/pkgs
       envs directories : /home/test_user/.conda/envs
                          /opt/conda/envs
               platform : linux-64
             user-agent : conda/23.1.0 requests/2.28.1 CPython/3.9.15 Linux/6.0.7 debian/11 glibc/2.31
                UID:GID : 1001:1001
             netrc file : None
           offline mode : False

Using the python script above in :

When I ran the docker container script again for each combination I would occasionally get 2.4.3 10 times and other times 3.0.3 10 times but it was always consistent within a singledocker run ....

So in all I haven't been able to reproduce yet.

jaimergp commented 1 year ago

So conda-libmamba-solver <= 22.8.1 (I guess this is the version you mean by 22.9.0) gives 3.0.3, but 22.12 gives 2.4.3 🤔 There are no big changes in the solver logic itself between the two releases (but they might be pinning different libmambas and libsolvs, we should also report these in the table). I'd take a look at #52 (shouldn't have an effect, these are fresh envs!) and #78 (nothing major catches my attention) for code changes but, again, I don't see how those have an effect on this. I think it's more about which libmamba versions are running with each.

What happens if we sample more than 10 attempts? Let's say 50?

PS: 22.6 is expected to be slower due to the "is there a new conda update?" checks.

costrouc commented 1 year ago

So conda-libmamba-solver <= 22.8.1 (I guess this is the version you mean by 22.9.0) gives 3.0.3, but 22.12 gives 2.4.3

@jaimergp I wouldn't read into it like that. I was getting 2.4.3 on some runs and 3.0.3 on some runs. I should have been more clear :smile:

costrouc commented 1 year ago

So I was able to reproduce this.

[('noarch', '2.4.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '2.4.3')]
[('noarch', '2.4.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '2.4.3')]

I went another route and just used github actions to see if I could reproduce the behavior to test linux/macos/windows as well and I could. Here is a reproducing run https://github.com/costrouc/conda-libmamba-solver-reproducibility/actions/runs/3964342931/jobs/6793117312#step:6:1

The actual workflow is here https://github.com/costrouc/conda-libmamba-solver-reproducibility/blob/master/.github/workflows/reproducible.yaml. I'll spend some time later trying the same this with checking out the git source for both projects.

costrouc commented 1 year ago

A full action running. I can reproduce the error:

Github actions doing the test https://github.com/costrouc/conda-libmamba-solver-reproducibility/actions/runs/3964442719/jobs/6793306009.

costrouc commented 1 year ago

Added git repo testing checking out the actual releases https://github.com/costrouc/conda-libmamba-solver-reproducibility/actions/runs/3964684703/jobs/6793761850#step:8:51 and can't reproduce it that way. This matches what you saw @jaimergp as well.

jaimergp commented 1 year ago

This is great news, @costrouc! So to summarize:

Differences I can think of between these contexts (OD=Outside-Docker, ID=Inside-Docker):

jaimergp commented 1 year ago

Ugh, yes, the initialization scripts in the Docker image are setting PYTHONHASHSEED T_T I think it comes from conda.core.initialize.initialize_dev (see this line). So I am sure it will reproduce in Docker if we do not set a seed. Clear the env var before running the tests and it should check out.

Details:

(base) test_user@8bb8f7890a4f:/opt/conda-libmamba-solver-src$ env | sort
CONDA_DEFAULT_ENV=base
CONDA_EXE=/opt/conda/bin/conda
CONDA_PREFIX=/opt/conda
CONDA_PROMPT_MODIFIER=(base) 
CONDA_PYTHON_EXE=/opt/conda/bin/python
CONDA_SHLVL=1
HOME=/home/test_user
HOSTNAME=8bb8f7890a4f
LANG=C.UTF-8
LC_ALL=C.UTF-8
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
OLDPWD=/opt/conda-src
PATH=/opt/conda/bin:/opt/conda/condabin:/opt/conda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/opt/conda-libmamba-solver-src
PYTHONHASHSEED=4243125599
PYTHON_MAJOR_VERSION=3
RUNNING_ON_DEVCONTAINER=
SHLVL=0
TERM=xterm
TEST_PLATFORM=unix
_=/usr/bin/env
_CE_CONDA=
_CE_M=

Edit - eureka:

[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '2.4.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '3.0.3')]
[('noarch', '2.4.3')]
jaimergp commented 1 year ago

Overall I think this is good news, because it means that the problem is on the Python side, so it should be very easy to fix. It must be a container without order guarantees, like a set or something.

jaimergp commented 1 year ago

The intriguing part is that libsolv seems to be sensitive to the input order o.o I wonder if we need to make sure and sort everything before passing things to libmamba, because python=3.8 bokeh>=1.0 holoviews>=1.1.0 might give different results than python=3.8 holoviews>=1.1.0 bokeh>=1.0.

maximlt commented 1 year ago

So nice to this being fixed, thanks so much guys for all the hard work reproducing the issue and fixing it! 👍 That was holding us, we're free to move to the libmamba world now :)

The intriguing part is that libsolv seems to be sensitive to the input order o.o I wonder if we need to make sure and sort everything before passing things to libmamba, because python=3.8 bokeh>=1.0 holoviews>=1.1.0 might give different results than python=3.8 holoviews>=1.1.0 bokeh>=1.0.

I would say that users with enough knowledge to understand that the SAT solver is a complicated thing to deal with wouldn't be overly surprised by this. All the others yes :)

jaimergp commented 1 year ago

We added tests to control for that too so we should be ok. The input specs were being sorted as they came, but then that order was lost before reaching libmamba because they were de-duped with a set(). Thank you so much for the report and patience!

LtDan33 commented 1 year ago

@maximlt Thanks for reporting this and glad it helped you out!