|
JP1 Remotes
|
View previous topic :: View next topic |
Author |
Message |
mathdon Expert
Joined: 22 Jul 2008 Posts: 4523 Location: Cambridge, UK |
Posted: Tue May 04, 2021 10:04 am Post subject: |
|
|
I have come across the following situation with Equation.solve in IrpTransmogrifier, which I believe to be an error:
1. Equation is (H:1:3^H:1:2)=0&1 with H=7&111.
solve() gives H=8&1000, which is the correct value for the unset bit H:1:3.
2. Equation is (H:1:2^H:1:3)=0&1 with H=7&111.
This is logically the same equation, but solve() gives H=0&100, which is false. _________________ Graham |
|
Back to top |
|
|
Barf Expert
Joined: 24 Oct 2008 Posts: 1415 Location: Munich, Germany |
Posted: Tue May 04, 2021 2:51 pm Post subject: |
|
|
The manual says Quote: | The decoder is capable of simple equation solving (e.g. Arctech), but not of complicated equation solving... |
Unfortunately, I see that my documentation is all but complete...
An equation can be solved with respect to ("wrt") the "left-most" quantity, while all other quantities are required to be known. So can for example
c*9/5 + 32 = 70
be solved wrt c, but
32 + c*9/5 = 70
or
9*c/5 + 32 = 70
cannot. (This is not Mathematica or Maple...) "Not a bug; a limitation". (Actually, with Graham's second equation, I get H = 0&0, i.e. no information at all, not the claimed 0&100.)
Graham, can you rewrite the equation so that the to-be-solved quantity is leftmost? I'll be happy to help if you give more details. |
|
Back to top |
|
|
mathdon Expert
Joined: 22 Jul 2008 Posts: 4523 Location: Cambridge, UK |
Posted: Tue May 04, 2021 4:59 pm Post subject: |
|
|
The equation concerned arises in performing the inverse of the definitions of the executor entry for X10-house. In developing that, I discovered by experiment that I needed the order to be H:1:3^H:1:2, as H:1:2^H:1:3 gave the wrong result. So I do not have a problem, but I decided today to investigate why the order was important. I thought it was my code that was at fault. My RMEquation.solve() tries your Equation.solve() with code of the form
Code: | if ( eq.solve() ) {
...
return;
}
code here handles the cases where eq.solve() returns false |
I understand that your code only handles simple equations and I have no quibble with that, but I believe it should return "false" on equations that it cannot handle, rather than returning an incorrect result, whether that be H=0&100 or H=0&0 as neither is the correct solution. _________________ Graham |
|
Back to top |
|
|
Barf Expert
Joined: 24 Oct 2008 Posts: 1415 Location: Munich, Germany |
Posted: Wed May 05, 2021 2:03 am Post subject: |
|
|
Actually, it is not as bad as you describe. In most cases of "unsolvable" equations, the solve() call returns false, as demonstrated by the following (TestNG) test (will check in as src/test/java/org/harctoolbox/irp/EquationNGTest.java):
Code: |
@Test
public void testSolveFail() throws NameUnassignedException {
System.out.println("solveFail");
Expression lhs = Expression.newExpression("32 + c*9/5");
long rhs = 70L;
Equation instance = new Equation(lhs, rhs);
boolean success = instance.solve();
assertFalse(success);
}
|
In your case 0&0 is returned, which means information on no bits available. I claim this is correct. Think about it, your equation
H:1:2^H:1:3)=0&1 with H=7&111
this is an equation for bit 0, the rightmost bit only. Shoving H:1:3 to the right hand side gives
H:1:2 = 0&1 ^ H:1:3
i.e. we are xor-ing the bit 0&1 with the third bit (counting from 0) of H, but (H=7&111), that bit is not known. What do we learn? Nothing! No valid information for H:1:2. This is what 0&0 means. Test:
Code: |
@Test
public void testSolveGraham2() throws NameUnassignedException, InvalidNameException, ParameterInconsistencyException {
System.out.println("solve");
Expression lhs = Expression.newExpression("H:1:2^H:1:3");
BitwiseParameter rhs = new BitwiseParameter(0L, 0b1L);
RecognizeData recognizeData = new RecognizeData();
recognizeData.add("H", new BitwiseParameter(7L, 0b111L));
Equation instance = new Equation(lhs, rhs, recognizeData);
boolean success = instance.solve();
assertTrue(success);
BitwiseParameter result = instance.getValue();
BitwiseParameter expResult = new BitwiseParameter(0L, 0L);
assertEquals(result, expResult);
}
|
I claim 0&0 is correct, and I would like to hear how you come up with 0&100. |
|
Back to top |
|
|
mathdon Expert
Joined: 22 Jul 2008 Posts: 4523 Location: Cambridge, UK |
Posted: Wed May 05, 2021 9:49 am Post subject: |
|
|
Barf wrote: | I would like to hear how you come up with 0&100. |
This comes from running Eclipse debugger in situ. Here are screenshots of the expression eq taken before and after the command eq.solve(). No other operation in between.
Before solving:
After solving:
Quote: | Think about it, your equation
(H:1:2^H:1:3)=0&1 with H=7&111
this is an equation for bit 0, the rightmost bit only. |
This makes no sense to me. This is a single-bit equation between three quantities, H:1:2, H:1:3 and 0:1:0. With H=7&111, H:1:2 evaluates to 1 and H:1:3 is undetermined. So the equation is
1^H:1:3=0
from which H:1:3=1. Exactly the same as if it were (H:1:3^H:1:2)=0&1. I know of no context in which the XOR operation is not commutative, which is apparently what you are saying. _________________ Graham |
|
Back to top |
|
|
Barf Expert
Joined: 24 Oct 2008 Posts: 1415 Location: Munich, Germany |
Posted: Thu May 06, 2021 5:57 am Post subject: |
|
|
I am sorry, the Eclipse screenshots do not constitute a reproducible experiment (see the code), and since it violates my (reproducable!) result from yesterday, I must assume that you are mistaken
Right. But as I wrote, equations are solved wrt the leftmost quantity (which is "1") in terms of the other quantities. Also for commutative operators.
Basically, I am somewhat reluctant to "put the OP knife" in this. It has worked for several years. Of course, it is some work, but more importantly, there is always the danger of introducing bugs or unwanted side effects -- although I have fairly extensive tests.
IrpTransmogrifier does not contain a generic equation solver. The rule is that equations are solved wrt the leftmost quantity, everything else being known.
If you can convince me that this is unacceptable, I will have a look into it. An realistic example (where you cannot just reorganize the terms in hand-written entries) would qualify. |
|
Back to top |
|
|
mathdon Expert
Joined: 22 Jul 2008 Posts: 4523 Location: Cambridge, UK |
Posted: Thu May 06, 2021 12:43 pm Post subject: |
|
|
I have only today looked at your test code and I see it contains the lines
Code: | RecognizeData recognizeData = new RecognizeData();
recognizeData.add("H", new BitwiseParameter(7L, 0b111L)); |
I would like to be able to use these instructions, but they are not visible outside of IrpTransmogrifier. The reason you get H=0&0 and I get H=0&100 is because it appears impossible for RMIR to put H=7&111 into RecognizeData. I have only just realized this, RMIR is putting H=7 with the default bitmask of -1. I have looked for a workaround but cannot find one. There appears to be no way for RMIR to attach bitmasks to values in RecognizeData. _________________ Graham |
|
Back to top |
|
|
Barf Expert
Joined: 24 Oct 2008 Posts: 1415 Location: Munich, Germany |
Posted: Thu May 06, 2021 1:34 pm Post subject: |
|
|
The reason that you are not allowed to use these instructions is that the constructor and the add(...)-function are declared packate private. I looked at the code, and could find no real reason for this decision, so I changed them to public. Found it the continuous build that should be available in a few minutes from now. (Commit 2fac43057b1ddfd656d691b9b823304c82137933) Please try it. |
|
Back to top |
|
|
mathdon Expert
Joined: 22 Jul 2008 Posts: 4523 Location: Cambridge, UK |
Posted: Sun May 09, 2021 8:51 am Post subject: |
|
|
Many thanks, Bengt. This solves the original problem, I now get H=0&0 rather than H=0&100, but it also goes much further than that. Access to these constructors may seem a simple change but it is leading me into a major rewrite of my RMEquation module, to both simplify and extend it, so very useful indeed. I will post more when I have explored further what I can now do. _________________ Graham |
|
Back to top |
|
|
mathdon Expert
Joined: 22 Jul 2008 Posts: 4523 Location: Cambridge, UK |
Posted: Sat May 15, 2021 12:19 pm Post subject: |
|
|
I have now posted to the SVN the revisions of my RMEquation and DeviceUpgradeExporter modules that I mentioned in my last post, together with the simplifications in rmProtocols.xml of the uei-executor entries for the various X10 protocols that these revisions have made possible. There is one further improvement I would like to make in the new coding, but it would need an additional method in RecognizeData. This is a public void remove(String name) method that performs parameterCollector.map.remove(name). I am currently using a workaround of copying the RecognizeData instance to a new instance, element by element but omitting the one I want to remove. This would be a natural counterpart to the add(..) method, if you feel like creating it. It is not essential for me, the workaround serves instead, but in my opinion it would make more satisfactory coding. _________________ Graham |
|
Back to top |
|
|
Barf Expert
Joined: 24 Oct 2008 Posts: 1415 Location: Munich, Germany |
Posted: Sun May 16, 2021 7:14 am Post subject: |
|
|
Just checked in the requested fix. |
|
Back to top |
|
|
mathdon Expert
Joined: 22 Jul 2008 Posts: 4523 Location: Cambridge, UK |
Posted: Sun May 16, 2021 12:53 pm Post subject: |
|
|
Many thanks, I have updated RMIR with this new snapshot and revised the modules concerned to make use of the "remove" method. This is now in the SVN. _________________ Graham |
|
Back to top |
|
|
Barf Expert
Joined: 24 Oct 2008 Posts: 1415 Location: Munich, Germany |
Posted: Wed May 19, 2021 10:34 am Post subject: |
|
|
By all means, feel free to request enhancements and extensions to the API. Likely, I will only reject anything if it can already be done with the existing things. It can sometimes be hard to anticipate what will be needed and what not. |
|
Back to top |
|
|
mathdon Expert
Joined: 22 Jul 2008 Posts: 4523 Location: Cambridge, UK |
Posted: Wed May 19, 2021 11:44 am Post subject: |
|
|
Thanks for the invitation to request enhancements. I think I am unlikely to find much that I would like, but here is something I have just come across today and find irritating. Not important, but irritating. I am still working on tidying the export of a Device Upgrade to a Girr file and was trying to get the parameters to be written to the file in the order that they are in the definitions section of the IRP. I was using a RC6-M-32 upgrade for which the definitions section is
Code: | [OEM1:0..255,OEM2:0..255,D:0..255,F:0..255,M:0..7,T@:0..1=0] |
The Girr command is constructed with a call to
Code: | Command(String name, String comment, String protocolName, Map<String, Long> parameters) |
where parameters is a LinkedHashMap with values in the definitions order. The T parameter is included if the upgrade has toggling set to none, and absent if toggling set to RC6 mode. The Girr file gives them in the order D,M,OEM1,F,OEM2 with toggling, D,T,F,M,OEM1,OEM2 with no toggling. Perfectly valid orders, but not very logical.
I see that the code for the Command method has
Code: | this.parameters = new HashMap<>(parameters) |
I suspect all that is required to maintain the order supplied in the instruction is to change HashMap to LinkedHashMap, though perhaps some other consequential changes may also be needed. I would appreciate it if you would consider this. _________________ Graham |
|
Back to top |
|
|
Barf Expert
Joined: 24 Oct 2008 Posts: 1415 Location: Munich, Germany |
Posted: Wed May 19, 2021 1:01 pm Post subject: |
|
|
First, what LinkedHashMap does is to maintain the insert order; when iterating over the entries, these will be delivered in the same order they were inserted. This is often convenient (but seldomly required), for example when testing an export method against a read file.
I suspect that just changing HashMap to LinkedHashMap will not have the desired effect, in particular if you want the parameters in a certain order, like the order in the IRP parameter specification. Possibly the TreeMap is more appropriate? Or to have a function Protocol.sortAsInParameterSpec(Map<String, Long> params) ? |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|