Open guilherme-marcello opened 1 month ago
After reviewing the issue in detail and exploring the relevant documentation, I have identified the cause of the problem and a few potential solutions.
The issue with the plot_surface
method arises from a mismatch between how the surface data (C
) is constructed and how numpy's meshgrid is used to generate the grid coordinates.
Specifically, the method currently constructs the surface data C
such that each row of C
corresponds to a fixed value of the first variable (e.g., service quality), while the meshgrid function
(with Cartesian indexing, the default indexing='xy') creates grids where this relationship is inverted. This leads to an incorrect mapping of variables in the plot, causing the surface to incorrectly depend on the wrong axis - as presented in the attached image.
The problematic loop in the current code is as follows:
for a in A:
temp = []
for b in B:
self.set_variable(v1, a)
self.set_variable(v2, b)
res = self.inference()[output]
temp.append(res)
C.append(temp)
C = array(C)
A, B = meshgrid(A, B)
Here, as described above, the variable C
is constructed with the assumption that each row corresponds to a constant value a
of v1
(e.g., service quality) and each column corresponds to a constant value b
of v2 (e.g., food quality). However, meshgrid
(with Cartesian xy indexing) swaps this arrangement when generating the A and B grids for plotting. So, as a result, plot_surface
plots the surface incorrectly.
I found three ways to fix it, that with some testings seemed to be reasonable.
We can fix the issue by changing the indexing mode in the meshgrid function to match how C
is constructed. Specifically, setting indexing='ij'
will use matrix indexing, which aligns with how the C
array is populated.
The change would be:
A, B = meshgrid(A, B, indexing='ij')
C
is constructed:Alternatively, we could modify the loop that constructs C
to reflect the Cartesian (xy) indexing used by meshgrid. This would involve swapping the roles of the variables inside the loop to ensure that C
is built consistently with Cartesian indexing.
We could rewrite the loop as follows:
for b in B:
temp = []
for a in A:
self.set_variable(v1, a)
self.set_variable(v2, b)
res = self.inference()[output]
temp.append( res )
C.append(temp)
C
Another simple fix is to transpose the C
array after it has been constructed. This approach corrects the mismatch between the way C
is built and how meshgrid expects the grid values to align, without needing to modify meshgrid's indexing mode. The added code in this fix is:
C = array(C)
C = C.T
While the solutions are valid, I would recommend the first one - changing the meshgrid indexing to 'ij' - since it involves fewer changes to the existing code and preserves the logic flow in plot_surface.
Please let me know if more information is required, and I would be happy to assist with further details or testing.
Guilherme.
Hello there,
It seems there is a bug in the plot_surface method of the FuzzySystem class that results in an incorrect surface plot.
In order to make the problem more evident, I changed slightly the code example provided in https://github.com/aresio/simpful/blob/master/examples/example_output_surface.py . The following code reproduces the issue:
The relevant change here is that a single rule "IF (Service IS excellent) THEN (Tip IS generous)" was added to the fuzzy system.
Observed output: The resulting plot (image bellow) incorrectly suggests that the tip increases with food quality instead of service quality.
The version of the packages I used in this execution:
I also replicated the issue with the following versions:
Is this really an unexpected behavior?
Thanks. Guilherme.