h2r / pomdp-py

A framework to build and solve POMDP problems. Documentation: https://h2r.github.io/pomdp-py/
MIT License
216 stars 50 forks source link

Random.choice behavior change in python 3.9 #52

Closed RajeshDM closed 8 months ago

RajeshDM commented 8 months ago

At Line 76 in Histogram.pyx, there is a random.choice function being used

https://github.com/h2r/pomdp-py/blob/588d59496b98b9f6a623d992578130d6cdac4db2/pomdp_py/representations/distribution/histogram.pyx#L76

The behavior of this function has changed in python 3.9 - if all the provided weights are 0, it returns the following error :

raise ValueError('Total of weights must be greater than zero') ValueError: Total of weights must be greater than zero

(I encountered the issue while running cos-pomdp where some of the correlation distributions all have 0 probability)

One other thing to note - in python 3.8 and older - if all the weights are 0, the random.choice function actually picks the last element of the list every time.

zkytony commented 8 months ago

If all weights are zero then it's not a valid probability distribution. The issue should be on the caller side. It would be good to look into why correlation distributions have 0 probability in cos-pomdp.

RajeshDM commented 8 months ago

If all weights are zero then it's not a valid probability distribution. The issue should be on the caller side. It would be good to look into why correlation distributions have 0 probability in cos-pomdp.

At this line - when all the correlation are being loaded, some of them all have 0 probabilities :

https://github.com/zkytony/cos-pomdp/blob/1e3c7fe940a2165b5c5c384ebf047e8139d437ec/cospomdp/models/correlation.py#L83

You can test this by running the following function :

    def load(loadpath):
        with open(loadpath, "rb") as f:
            data = pickle.load(f)
        dists = {}
        for starget in data['dists']:
            weights = data['dists'][starget]
            dist = TabularDistribution([data['corr_object'][0]],
                                        weights, normalize=True)
            dists[starget] = dist

        for dist in dists.values():
            if sum(dist.histogram.values()) == 0 :
                candidates = list(dist.histogram.keys())
                prob_dist = []
                for value in candidates:
                    prob_dist.append(dist.histogram[value])
               print (random.choices(candidates, weights=prob_dist, k=1)[0],sum(prob_dist))

This is basically happening right after the corelation probabilities being loaded - so it looks like the stored data has the 0s

zkytony commented 8 months ago

Sorry, since this is code in cos-pomdp, could you post there ?

RajeshDM commented 8 months ago

Will do. Thanks