Replies: 11 comments
-
Hi theo, thanks for reporting this bug. I suspect there is an overflow somewhere in the solver, it will be hard to identify. Here is a quick fixup, if it suits your need. Normalizing M by dividing it by its maximum value does not change the solution and it behaves more consistently: |
Beta Was this translation helpful? Give feedback.
-
Should we normalize like that the M matrix inside emd then? This is weird because it seemed to me that when using np.inf in the M matrix the exact solver works very well. |
Beta Was this translation helpful? Give feedback.
-
Note that compiling network_simplex_simple.h with a positive DEBUG_LVL does not work ( |
Beta Was this translation helpful? Give feedback.
-
@ncourty I may be missing something but I tried the same code using normalization in the I also tried using Code to reproduce (updated version of the previous code):
Output:
|
Beta Was this translation helpful? Give feedback.
-
interesting bug, i will try to reproduce it on my machine and get back to you. |
Beta Was this translation helpful? Give feedback.
-
A bit simplified import numpy as np
import ot
z = 1e16
M = np.array([[1, z, 0], [1, z, 0], [z, 0, z], [0, z, 0]])
b = np.array([1, 1, 3])
a = np.array([1, 1, 1, 2])
P = ot.emd(a=a, b=b, M=M)
Q = np.array([[0, 0, 1], [0, 0, 1], [0, 1, 0], [1, 0, 1]])
assert (P.sum(axis=0) == b).all()
assert (P.sum(axis=1) == a).all()
assert (Q.sum(axis=0) == b).all()
assert (Q.sum(axis=1) == a).all()
print("my cost matrix:\n", Q)
print("POT matrix:\n", P)
print("POT cost:", np.sum(np.multiply(P, M)))
print("my cost:", np.sum(np.multiply(Q, M)))
Could be related to EPSILON or the precision of |
Beta Was this translation helpful? Give feedback.
-
yes that's it good catch! basically we cannot solve the problem precisely if there exist two values different values in m such that m_1+_2=m_1 due to numerical precision. I dont' think we can say it is a bug or something we can solve if it is due to the numerical precision for float64. Maybe we can add a warning when the dynamic in M is too large. Note that if you want to forbid a link you just need to set its value to M.max()*1.0001 or something like that instead of a very large value, it will not change the solution or the value. Again thank you for reporting this weird behavior. |
Beta Was this translation helpful? Give feedback.
-
Well, it isn't impossible. If m_1 is not used in the optimal plan, it is possible to compute the optimal plan without relying on something like
Just around the max of the other values may not be sufficient to forbid a link, it could still be used to transport a small mass in the optimal plan. |
Beta Was this translation helpful? Give feedback.
-
POT exact OT solver is a wrapper around the C++ LEMON solver and we modifying it is out of what we can do. In addition, it might require some kind of testings at each iteration that could greatly decrease the performance. About the max value, I think it is sufficient if the dynamic in M is limited (below 1e14 for instance) adding a cost that is bigger than all the other would prevent any mass on the link because the solver is a Network simplex and the solution will always be on a face of the polytop and under the dynamic condition this face can be improved if there is mass on the largest values of M. |
Beta Was this translation helpful? Give feedback.
-
ok, thanks.
Yes, although since I am not familiar with the algorithm I have no idea how large the cost would be.
|
Beta Was this translation helpful? Give feedback.
-
you are right good example |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Describe the bug
It seems
ot.emd
fails to return an optimal plan (up to numerical precision) if there is large entries in the cost matrix (even if the optimal weight to put on these entries is 0).To Reproduce
returns:
Expected behavior
ot.emd
should return (up to numerical precision) a transport plan (at least) as good as theQ
I manually propose.Environment (please complete the following information):
pip
,conda
): condaOutput of the following code snippet:
Additional context
As shown, I set
numIterMax
at2000000
and didn't get any warning (and the code run fast) so the algorithm does converge.Beta Was this translation helpful? Give feedback.
All reactions