diff --git a/.github/workflows/pypi_deployment.yml b/.github/workflows/pypi_deployment.yml index 86214ed..203b608 100644 --- a/.github/workflows/pypi_deployment.yml +++ b/.github/workflows/pypi_deployment.yml @@ -47,7 +47,7 @@ jobs: working-directory: . run: | cd scripts - ./pomdp_py_release.sh ${{ vars.RELEASE_ATTEMPT_COUNT }} + ./pomdp_py_release.sh - name: Upload to Test PyPi uses: pypa/gh-action-pypi-publish@release/v1 @@ -98,7 +98,7 @@ jobs: working-directory: . run: | cd scripts - ./pomdp_py_release.sh ${{ vars.RELEASE_ATTEMPT_COUNT }} + ./pomdp_py_release.sh - name: Upload to PyPi uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 97764ef..709456a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,12 @@ Changelog Best viewed on `the website `_. +Version 1.3.5.1 (03/30/2024) +---------------------------- +* Hot fixes for :py:mod:`~pomdp_py.representations.distribution.particles.WeightedParticles`. +* :py:mod:`~pomdp_py.framework.basics.Agent` can be created with a name. +* Bug fixes for release script and GHA workflow. + Version 1.3.5 (03/12/2024) -------------------------- * Refactored :code:`_search` in :py:mod:`~pomdp_py.algorithms.po_uct.POUCT` to be more modular diff --git a/pomdp_py/representations/distribution/particles.pyx b/pomdp_py/representations/distribution/particles.pyx index 323208f..e598885 100644 --- a/pomdp_py/representations/distribution/particles.pyx +++ b/pomdp_py/representations/distribution/particles.pyx @@ -13,7 +13,7 @@ cdef class WeightedParticles(GenerativeDistribution): Args: particles (list): List of (value, weight) tuples. The weight represents - the likelihood that the value is drawn from the underlying distribution. + the likelihood that the value is drawn from the underlying distribution. Note that the weights may not be normalized. To normalize, call condense(). approx_method (str): 'nearest' if when querying the probability of a value, and there is no matching particle for it, return the probability of the value closest to it. Assuming values diff --git a/pyproject.toml b/pyproject.toml index ff42c20..2a27e90 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "pomdp-py" -version = "1.3.5" +version = "1.3.5.1" description = "Python POMDP Library." authors = [{name = "Kaiyu Zheng", email = "kzheng10@cs.brown.edu"}] license = {file = "LICENSE"} diff --git a/scripts/pomdp_py_release.sh b/scripts/pomdp_py_release.sh index d9cd79b..07db750 100755 --- a/scripts/pomdp_py_release.sh +++ b/scripts/pomdp_py_release.sh @@ -70,6 +70,21 @@ extract_package_version() { echo "$version" } +get_base_version() { + version_string="$1" + echo "${version_string%-*}" +} + +get_post_version() { + version_string="$1" + if [[ "$version_string" == *-* ]]; then # Check if hyphen exists + echo "${version_string##*-}" + else + echo "" # Output an empty string if no hyphen found + fi +} + + user_pwd=$PWD # Write the MANIFEST.in file @@ -79,12 +94,17 @@ cd $pomdp_py_path find_pxd_files_and_write_manifest ./ MANIFEST.in # Check if pomdp-py is on the right branch -version=$(extract_package_version "$pomdp_py_path/pyproject.toml") -attempt_count="" -if [ $# -gt 0 ]; then - attempt_count="-$1" +package_version=$(extract_package_version "$pomdp_py_path/pyproject.toml") +base_version=$(get_base_version $package_version) +post_version=$(get_post_version $package_version) + +if [[ -n "$post_version" ]]; then # Check if $post_version is not empty + version="${base_version}.post${post_version}" +else + version="$base_version" fi -echo $version + +echo "RELEASE VERSION: $version" if ! is_git_repo_on_branch $pomdp_py_path dev-$version; then if ! is_git_repo_on_branch $pomdp_py_path dev-latest; then echo "pomdp-py repo must be either on dev-latest or dev-$version, but not $current_branch. Abort" @@ -114,14 +134,13 @@ command="auditwheel repair io/dist/${wheel_name} -w /io/wheelhouse/" docker run --user $(id -u):$(id -g) --mount type=bind,source=${pomdp_py_path},target=/io $manylinux_image bash -c "$command" rm $pomdp_py_path/dist/$wheel_name fixed_wheel_name="pomdp_py-${version}-${cpv}-${cpv}-manylinux_2_17_x86_64.$linux_dist.whl" -fixed_wheel_name_with_attempt="pomdp_py-${version}${attempt_count}-${cpv}-${cpv}-manylinux_2_17_x86_64.$linux_dist.whl" -mv "$pomdp_py_path/wheelhouse/$fixed_wheel_name" "$pomdp_py_path/dist/$fixed_wheel_name_with_attempt" +mv "$pomdp_py_path/wheelhouse/$fixed_wheel_name" "$pomdp_py_path/dist/$fixed_wheel_name" rm -r $pomdp_py_path/wheelhouse # Verification (wheel) echo -e "------------ verification: wheel ---------" pip uninstall pomdp_py -pip install --force-reinstall "$pomdp_py_path/dist/$fixed_wheel_name_with_attempt" +pip install --force-reinstall "$pomdp_py_path/dist/$fixed_wheel_name" python $pomdp_py_path/tests/test_all.py # Verification (source) diff --git a/tests/test_particles.py b/tests/test_particles.py index bb0a5f8..c906d43 100644 --- a/tests/test_particles.py +++ b/tests/test_particles.py @@ -5,6 +5,7 @@ def test_particles(): + random.seed(100) random_dist = {} total_prob = 0 for v in range(4): @@ -36,6 +37,7 @@ def test_particles(): def test_weighted_particles(): + random.seed(100) random_dist = {} total_prob = 0 for v in range(5): @@ -45,6 +47,9 @@ def test_weighted_particles(): particles = pomdp_py.WeightedParticles.from_histogram(random_dist) particles_frozen = pomdp_py.WeightedParticles(particles.particles, frozen=True) + assert particles.hist_valid + assert particles_frozen.hist_valid + assert abs(sum(particles[v] for v, _ in particles) - 1.0) <= 1e-6 assert abs(sum(particles_frozen[v] for v, _ in particles_frozen) - 1.0) <= 1e-6 @@ -52,6 +57,7 @@ def test_weighted_particles(): assert abs(particles[v] - random_dist[v] / total_prob) <= 2e-3 assert abs(particles_frozen[v] - random_dist[v] / total_prob) <= 2e-3 + # Test sampling counts = {} total = int(1e6) for i in range(total): @@ -66,6 +72,25 @@ def test_weighted_particles(): assert particles_frozen.mpe() == pomdp_py.Histogram(random_dist).mpe() hash(particles_frozen) + # Manually add a particle - this changes the distribution + particles.add(("x1", 0.1)) + assert not particles.hist_valid + particles.random() # operation does not re-compute histogram + assert not particles.hist_valid + pr_x1 = particles["x1"] # operation will re-compute histogram + assert particles.hist_valid + + # However, weights won't sum up to 1 due to the additional particle + assert abs(sum(particles[v] for v, _ in particles) - 1.0) > 1e-6 + + # After condensing, weights sum up to 1 + particles = particles.condense() + assert abs(sum(particles[v] for v, _ in particles) - 1.0) <= 1e-6 + + # Test frozen after condense + assert not particles.condense().frozen + assert particles_frozen.condense().frozen + def run(): test_particles()