-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Domain resolution value changes output value... #55
Comments
Well observed. There is some debate on this problem here #47. |
Well, here is the situation I am in. I am interested in applying fuzzy logic to some engineering problems. The first attempted application is in calculating the impedance of a microstrip transmission line. The thinner the line, the higher the impedance, the thinner the line, the lower the impedance. Currently, I have a routine which will iterate over different width of the transmission line to calculate an impedance, compare it to the target impedance and stop when the target impedance is close enough to calculated impedance. It is my desire to use fuzzy logic and very the amount of change applied to the trace width as we calcuate new impedances. The basic idea is that the larger the error between the target impedance and the desired impedance the more we change the width of the trace. as we get closer to the desired impedance the smaller the change. As I am new to fuzzy logic, and I really like the implementation of your code, I would like to understand how to implement a simple set of fuzzy logic calculations to determine the change in width to be applied to the trace based on the magnitude of the impedance error. Below is my test code for attempting to implement the calculations for determining the change in width to be applied to the traces. There are sections which are commented out for plotting the graphs of the veriables involved. I have set up a loop which will run through different errors from large negative errors to large positive errors. The expected outcome is for the width changes to start out large positive, approach 0, and then proceed to large negative numbers. If the code below is run, the change in width which is output is practically constant. I do not understand where things are going horribly wrong... If there is any guidance you could suggest, I would greatly appreciate the suggestions... This code is to be used in another program which calculates the impedance of a The purpose of this routine is to determine the delta between the The impedance error is the error between the desired impedance and the calculated The trace_delta will be the amount that the trace width will be modified by The idea being the bigger the impedance error, the larger the modification to the trace
|
Tried to fix the formatting for the code segment.. |
You need to use backticks ``` to format a block as code. There, I fixed it for you. |
|
trace_delta = Domain( "Delta", -2, 2 ) looks weird. This assumes a resolution of 1, which is only the values of [-2, -1, 0, 1, 2], no? Is that what you intend? This is where the resolution issue arose. Originally, I had the resolution set to 0.01 as I felt this would be a good incremental value for changing the width. When I was getting results which did not make sense to me, I started experimenting with other resolutions. That piece of code is simply the point where I had eliminated the resolution to see if there would be a difference in the output characteristic. There was not. It was at this point where I thought I would seek the advise of a resonsible adult who could perhaps show me the error of my ways. |
Reasonable? Me? Uhmmm... 😆 Well. "Eliminating" the resolution just means defaulting to 1 in this case. The problem with the resolution probably is with line 493 in classes.py, the final defuzzification step. You can try to experiment and see if you can figure out a better solution?
|
Btw, thanks a lot for your actual usecase. Helps so much in understanding how my code is actually used and how it's supposed to work. Last person who contacted me wanted me to implement stuff without giving any clue on how it's supposed to work due to "intellectual property" BS. Made me wonder if I should've licensed the lib with GPL3 instead... 🙄 |
Hmmm. Could the problem with the resolution be caused by the negative lower limit in the domain? I'm just trying to reproduce your problem and having a result of -3.2 in a domain that has -2 as lower bound really is an obvious bug. |
Thank you for taking the time to look at the code. I also noticed that there were cases where the output would be outside the domain. If the inputs were outside their domain then I would not be surprised at something like that happening. However, if all the values are within the approriate domains, I would not expect that output. When I run the code, it appears that the output is stuck, or biased, toward the lower end of the domain. I am not sure that I would expect the results to be rounded to the resolution if there is interpolation occuring, but if there is no interpolation, then yes, I would expect a result at some value in the domain that is a multple of the resolution... In examing things this morning, I was checking to see if the impedance_error, for the various test values, was giving values that made sense. It appears that reasonable values were being returned. This only leaves the application of the various rules returning incorrect values. I was waiting to hear what your thoughts were befroe trying to dive in any deeper as I only have a cursory understanding of the mathematics behind the transformations being applied. |
I have a question concerning the center of gravity calculation (this is where I think things are going horribly wrong): I modifed the code to print out values of various things:
temp_value is the same as the return value. The index value contains a calculation of the center_of_gravity (cog), I print out the cog value from center_of_gravity. For the program that I run with the last value of imepedance_error = 100, I get the following output: pos_large: weights = array([0. , 0. , 0. , 0. , 0. , The array for pos_large I believe. It looks reasonable. Zeros for the beginng, a transition region, and the last values all 1. So I would say that is correct. The self.domain.range also looks goot (-2 to 2 with a res=0.1). That is fine. cog value of 1.298, assuming the np.average calculation is done correctly (and why wouldn't it), seems like a reasonable answer. The index value is the same as cog. This is not what I would expect. I would expect the index to be an integer which is an index into the array which is closest to 1.298, as such, I would expect an integer and not a float. using index as an index into the domain (-2 to 2 with res=0.1) is going to return a value very close to -2, which is what appears to be happening looking at temp_value = -1.9870521763224789. So, it seems to me that the index value is not correct. I am not wise enough to work on fixing the code to get and actual index. Perhaps this is something you could look at and see if what I am saying is correct or not. Thank you very much |
Seems like you've done a lot of digging, wow. Okay. Hmm. Let's see... |
I would expect the index to be an integer which is an index into the array which is closest to 1.298, as such, I would expect an integer and not a float. The return calculation (which should return the appropriate delta value to applied to the width) is attempting to return the value which is closest to 1.298 (which is the cog value returned). The calculation takes the span of the domain, divides it by the number of values in this range, (essentially getting res=0.01 value), multiplies by the index to get the number of res=0.01 steps which corresponds to the closest value of 1.298, and then adds the low value of the domain to obtain that value... since this returns the closes value to the cog, why not just return the cog? Or, take the cog value and divide by res=0.01 add 0.5 and take the integer value to get the index into the array, and return that value at that index... seems like just returning the cog would be good enough to me... |
Sorry, I deleted my comments after re-reading what you posted in detail. As I understand it, the index is not an integer because at this point in the calculation it's basically an inversion of the axis and the index is abstract - you've calculated the y values, weighted them and then you've got an x value, which is not an actual array index, but rather stands for the relative position inside the continuous, but limited domain. This last step attempts to re-map the relative position inside the domain to the absolute number, taking into account the limits. |
There is an alternative approach to using arrays, which could actually be intermixed. Simple functions like R, S, triangular, trapezoid could be mapped to actual geometric formulas, so the "index" would really be the x-value of your graph. I hope that clears it up. |
well, I changed the code to simply return the cog value and I appear to be actually getting usable results. Like I said, I am no expert on this subject, but you statement above pretty much agrees with my observation. In fact, your statement "the index is abstract - you've calculated the y values, weighted them and then you've got an x value, which is not an actual array index, but rather stands for the relative position inside the continuous, but limited domain.", which I agree with (and that is my point), index which is calculated is NOT an index into the array, but it is being treated as if it is... I also believe your statement "As I understand it, the index is not an integer because at this point in the calculation it's basically an inversion of the axis" I also agree with, and I believe that the cog calculation is performing that inversion and giving you this inverted value which is being calculated as the cog... As I am not an expert, and have no experience in any of this, this could very well be a coincidence and I am completely wrong... |
What's the cog value you return now? |
Sorry, I was busy for a couple of days and didn't have time to look at this discussion. From the above output, the cog = 1.2980193236714976. This is instead of the erroreous -1.9870521763224789. From the looks of the self.domain.range, this looks like it is a reasonable answer. |
I would like to ask you a favor. I think the way forward is test-driven. This means I need the simplest possible example for the different combinations of domains with ranges from negative-negative, negativ-zero, zero-positive, positive-positive and different resolutions with their respective expected results. Could you construct a few of those examples which I can turn into tests? Key points are "obvious" and "simple" so there are no ambiguities on when the code is wrong. |
HI there. Sorry it has taken so long to respond. I got busy with work and had to put this problem aside for a time. Let me have a think about this and see if there is anything I can generate. |
In the showcase example of HVAC motor control, the Domain for the motor is defined as follows:
motor = Domain( "Speed", 0, 2000 )
When the example code is run, it results in an output of 1633.122481617619
when the domain has a resolution added as follows:
motor = Domain( "Speed", 0, 2000, 0.1 )
the output when run is then 163.36247274216137
It would appear that changing the resolution is altering the scale of the output -> resolution reduced by an order of magnitude results in an output reduction of an order of magnitude. I do not believe that this is mentioned in the documentation.
Is this the intended result of additing resolution to the domains? Does adding the resolution to the inputs (temperature and humidity in this example) have any scaling consequences?
Thank you very much
The text was updated successfully, but these errors were encountered: