Need help with RPL Listing for "SOLVER FOR ANY VARIABLE" - Printable Version +- HP Forums (https://www.hpmuseum.org/forum) +-- Forum: HP Calculators (and very old HP Computers) (/forum-3.html) +--- Forum: General Forum (/forum-4.html) +--- Thread: Need help with RPL Listing for "SOLVER FOR ANY VARIABLE" (/thread-13243.html) Need help with RPL Listing for "SOLVER FOR ANY VARIABLE" - Namir - 07-07-2019 08:45 PM Hi All, I have a presentation for HHC2019 that Richard Nelson asked me to do. It is a multi-variable solver. Meaning that given an equation with N variables, you can solve for any variable given fixed values for the remaining N-1 variables. I would like an RPL version (see teh HP-71B and HP-4C versions that solve for any variable in simple financial equation FV=PV*(1+i)^n). I will give credit to the author of the author of the version I will use in my presentation. I will also mention that author in my presentation that will appear on YouTube. Here is the HP-71B Listing Code: ```10 REM SOLVER FOR ANY VARIABLE 20 DIM X(20) 30 READ N, K, T 40 DATA 4, 1, 1E-7 50 FOR I=1 TO N 60 IF I=K THE DISP "GUESS FOR "; 70 DISP "X(";I;")"; @ INPUT X(I) 80 NEXT I 90 H = 0.01*(1 + ABS(X(K))) 100 GOSUB 1000 @ F0 = F 110 X0=X(K) @ X(K) = X0 + H 120 GOSUB 1000 130 D = H * F0 /(F - F0) 140 X(K) = X0 - D 150 IF ABS(D) > T THEN 90 160 DISP "ROOT = ";X(K) 1780 END 1000 REM CALCULATE F(X)=0 1001 REM X(1) = FV = PV*(1+I)^N 1002 REM X(2) = PV 1003 REM X(3) = I 1004 REM X(4) N 1010 F = X(1)-X(2)*(1+X(3))^X(4) 1020 RETURN``` For an HP-41C Code, here is the memory map: Code: ```R00 = I R01 = X(1) R02 = X(2) .... R20 = X(20) R21 = N R22 = K R23 = Toler R24 = h R25 = F0 R26 = D R27 = X0``` And here is the HP-41C Listing: Code: ```LBL "MVSOLV" LBL A "N?" PROMPT STO 21 1E3 / 1 + STO 00 "K?" PROMPT STO 22 "TOLER?" PROMPT STO 23 LBL 00        # Input variables RCL 22 RCL 00 INT CLA X#Y? "GUESS " |-"X<" FIX 0 ARCL X |-">?" FIX 5 PROMPT STO IND 00 ISG 00 GTO 00        # end of input loop LBL 01 RCL IND 22 ABS 1 + 0.01 * STO 24        # calculate and store h XEQ E STO 25        # calculate F0 RCL IND 22 STO 27        # X0 = X(K) RCL 24 STO+ IND 22    # X(K) = X(K) + h XEQ E RCL 25 - 1/X RCL 25 * RCL 24 * STO 26        # Diff = X(K) - f(X(K)) / f'(X(K)) RCL 27 - CHS STO IND 22    # X(K) = X(K) - Diff RCL 26 ABS RCL 23 X>``` By the way, if it's only the financial equation you are interested in solving, the 50g has the full TVM solver, just setting the payment amounts to 0 you end up with the equation above. That also has a nice UI built-in. RE: Need help with RPL Listing for "SOLVER FOR ANY VARIABLE" - DavidM - 07-08-2019 06:26 PM Namir, if you're simply wanting an RPL version of the same program logic that you're using in the other supplied programs, then the following may provide a starting point. This is meant to mimic your 71B structure/flow as closely as possible, and uses the same variable names that you specified in that version. As Claudio has mentioned, the built-in solver would be better to use, but I'm guessing you simply want to have an RPL equivalent to the other programs. That's what I've attempted to do here. Code: ```\<<    0. 20. NDUPN \->ARRY          @ X[]    4.                            @ N    1.                            @ K    1E-7                          @ T    'X(1)-X(2)*(1.+X(3))^X(4)'    @ F    0. DUPDUP DUP                 @ F0, X0, H, D    \-> X N K T F F0 X0 H D    \<<       @ obtain X values       1. N FOR index          "X("          IF             index K SAME          THEN             "Guess for " SWAP +          END          index R\->I \->STR +          "):" +          "" INPUT STR\->          'X' index ROT PUT       NEXT       @ repeat until current delta within specified tolerance       DO          X K GET ABS 1. + 0.01 *          'H' STO          F \->NUM          'F0' STO          X K GET          'X0' STO          'X' K          X0 H +          PUT          H F0 * F \->NUM F0 - /          'D' STO          'X' K          X0 D -          PUT       UNTIL          D ABS T \<=       END       @ output X(K)       X K GET "Root" \->TAG    \>> \>>``` No attribution needed, you (and everyone else) should feel free to make improvements or modify however you like. My goal in this case was to replicate the same logic flow as the other programs as opposed to focusing on code size, speed, or special RPL features. I used an algebraic for F in this case to make the coding a closer match to the 71B version. If logic flow parity wasn't your intended target for this, please ignore and move on. Hope this helps! - David RE: Need help with RPL Listing for "SOLVER FOR ANY VARIABLE" - Namir - 07-08-2019 09:25 PM Thank you David. Your ode will beautifully do the job!!! Richard Nelson wanted a geneal RPL code that would also work with the HP-48GX. Namir RE: Need help with RPL Listing for "SOLVER FOR ANY VARIABLE" - DavidM - 07-08-2019 09:45 PM (07-08-2019 09:25 PM)Namir Wrote:  ...that would also work with the HP-48GX. Oops! I wrote that code with a 50g target, and I know of at least one command it uses (R→I) that isn't applicable to the 48 series. I'm also not sure if array indexing with subscripts works the same way on a 48, so I may need to adjust that as well. I'll redo this and post an update after I've had a moment to go through it with the 48GX as a target (hopefully later this evening). RE: Need help with RPL Listing for "SOLVER FOR ANY VARIABLE" - DavidM - 07-08-2019 11:52 PM So there were actually 3 commands not supported on a 48GX, and I was right about the array subscripts (which are not supported on the 48 series). Also, one additional layer of locals is now needed since the function F references locals from the array that have to already have been declared and in-scope -- being able to define it as an algebraic in the previous example worked around that issue. I also rearranged the input loop a bit to make it easier to read (IMHO). It's always surprising to me how often I use commands and features that didn't come into play until the 49-50 series. It doesn't "feel" like I do it that often when I'm coding, but on those rare occasions when I write 48-series code I see the evidence firsthand. Code: ```\<<    { 20 } 0 CON                  @ X[]    4                             @ N    1                             @ K    1E-7                          @ T    0 DUP DUP DUP                 @ F0, X0, H, D    \-> X N K T F0 X0 H D    \<<       \<<                        @ F          @ X(1)-X(2)*(1+X(3))^X(4)          X 1 GET          X 2 GET          X 3 GET 1 +          X 4 GET ^          * -       \>>       \-> F       \<<          @ obtain X values          1 N FOR index             "X(" index \->STR + "):" +             IF                index K SAME             THEN                "Guess for " SWAP +             END             "" INPUT STR\->             'X' index ROT PUT          NEXT          @ repeat until current delta within specified tolerance          DO             X K GET ABS 1 + 0.01 *             'H' STO             F EVAL             'F0' STO             X K GET             'X0' STO             'X' K             X0 H +             PUT             H F0 * F EVAL F0 - /             'D' STO             'X' K             X0 D -             PUT          UNTIL             D ABS T \<=          END          @ output X(K)          X K GET "Root" \->TAG       \>>    \>> \>>``` Note: I'm just transcoding here, so I'm not asserting that this program is fully debugged and operational. I haven't done much testing -- just a couple of basic scenarios which seem to work. Question: Have you insured in the algorithm that the indefinite loop exit condition is guaranteed to occur? In other words, is it possible that some inputs might cause the "delta" to always be greater than the tolerance value? RE: Need help with RPL Listing for "SOLVER FOR ANY VARIABLE" - Namir - 07-09-2019 01:06 AM Quote:Question: Have you insured in the algorithm that the indefinite loop exit condition is guaranteed to occur? In other words, is it possible that some inputs might cause the "delta" to always be greater than the tolerance value? Good point. Here is the HP-71B BASIC listing using a new variable M to control the maximum number of iterations: Code: ``` 10 REM SOLVER FOR ANY VARIABLE 20 DIM X(20) 30 READ N, K, T, M 40 DATA 4, 1, 1E-7, 50 50 FOR I=1 TO N 60 IF I=K THE DISP "GUESS FOR "; 70 DISP "X(";I;")"; @ INPUT X(I) 80 NEXT I 90 H = 0.01*(1 + ABS(X(K))) 100 GOSUB 1000 @ F0 = F 110 X0=X(K) @ X(K) = X0 + H 120 GOSUB 1000 130 D = H * F0 /(F - F0) 140 X(K) = X0 - D 145 M = M - 1 150 IF ABS(D) > T AND M > 0 THEN 90 160 DISP "ROOT = ";X(K) 1780 END 1000 REM CALCULATE F(X)=0 1001 REM X(1) = FV = PV*(1+I)^N 1002 REM X(2) = PV 1003 REM X(3) = I 1004 REM X(4) N 1010 F = X(1)-X(2)*(1+X(3))^X(4) 1020 RETURN``` Here is the update memory map for the HP-41C to include R28 to store the maximum number of iterations. Code: ```R00 = I R01 = X(1) R02 = X(2) .... R20 = X(20) R21 = N R22 = K R23 = Toler R24 = h R25 = F0 R26 = D R27 = X0 R28 = MAX_ITERS``` And here is the HP-41C listing that uses register R28 to control the maximum number of iterations: Code: ```LBL "MVSOLV" LBL A "N?" PROMPT STO 21 1E3 / 1 + STO 00 "K?" PROMPT STO 22 "TOLER?" PROMPT STO 23 "MAXITERS?" PROMPT STO 28 LBL 00        # Input variables RCL 22 RCL 00 INT CLA X#Y? "GUESS " |-"X<" FIX 0 ARCL X |-">?" FIX 5 PROMPT STO IND 00 ISG 00 GTO 00        # end of input loop LBL 01 RCL IND 22 ABS 1 STO- 28        # MAX_ITRER = MAX_ITET - 1 + 0.01 * STO 24        # calculate and store h XEQ E STO 25        # calculate F0 RCL IND 22 STO 27        # X0 = X(K) RCL 24 STO+ IND 22    # X(K) = X(K) + h XEQ E RCL 25 - 1/X RCL 25 * RCL 24 * STO 26        # Diff = X(K) - f(X(K)) / f'(X(K)) RCL 27 - CHS STO IND 22    # X(K) = X(K) - Diff RCL 26 ABS RCL 23 RCL 28 X=0? GTO 02 RDN X X N K T M F0 X0 H D flags    \<<       @ setup function F       \<<          @ X(1)-X(2)*(1+X(3))^X(4)          X 1. GET          X 2. GET          X 3. GET 1. +          X 4. GET ^          * -       \>>       \-> F       \<<          @ obtain X(n) values from user          0. FIX          1. N FOR index             index K SAME "Guess for " "" IFTE             "X(" +             index \->STR             1. OVER SIZE OVER - SUB +             "):" +             "" INPUT STR\->             'X' index ROT PUT          NEXT          @ repeat until either:          @   1) current delta within specified tolerance, or          @   2) M passes have elapsed          DO             X K GET ABS 1. + 0.01 *             'H' STO             F EVAL             'F0' STO             X K GET             'X0' STO             X0 H +             'X' K ROT PUT             H F0 * F EVAL F0 - /             'D' STO             X0 D -             'X' K ROT PUT          UNTIL             D ABS T \<=             'M' DECR NOT             OR          END          @ output X(K)          X K GET "Root" \->TAG          @ restore flag settings          flags STOF       \>>    \>> \>>``` RE: Need help with RPL Listing for "SOLVER FOR ANY VARIABLE" - Namir - 07-10-2019 05:02 AM Thanks David!!!! Namir RE: Need help with RPL Listing for "SOLVER FOR ANY VARIABLE" - DavidM - 07-11-2019 01:25 PM One more RPL version... This one is a bit more of a traditional RPL approach. Instead of replicating the exact flow of the 71B steps, it uses the stack for holding the temporary variables F0, X0, H, and D while seeking the root. This makes better use of the calculator's resources (saves 116.5 bytes and executes faster), but also makes the source much harder to read and maintain (IMHO). In many ways, this follows the usual pattern for RPL (and RPN) code: the more refined and efficient it is, the more fragile it becomes. Whereas in the previous version you could actually see the temporary variable modifications, holding the variables on the stack during execution makes it much harder to follow simply by looking at the code. If the comments are removed, it would be an arduous task to go back and make changes. Code: ```\<<    @ setup local variables    { 20. } 0. CON                @ X(20)    4. 1. 1E-7 50.                @ N, K, T, M    RCLF                          @ flags    \-> X N K T M flags    \<<       @ setup function F       \<<          @ X(1)-X(2)*(1+X(3))^X(4)          X 1. GET          X 2. GET          X 3. GET 1. +          X 4. GET ^          * -       \>>       \-> F       \<<          @ obtain X(n) values from user          0. FIX          1. N FOR index             index K SAME "Guess for " "" IFTE             "X(" +             index \->STR             1. OVER SIZE OVER - SUB +             "):" +             "" INPUT STR\->             'X' index ROT PUT          NEXT          @ repeat until either:          @   1) current delta within specified tolerance, or          @   2) M passes have elapsed          DO             F EVAL                        @ F0=F             X K GET                       @ X0=X(K)             DUP ABS 1. + 0.01 *           @ H=0.01*(1+ABS(X(K)))             DUP2 + 'X' K ROT PUT          @ X(K)=X0+H             ROT F EVAL OVER - / *         @ D=H*F0/(F-F0)             SWAP OVER - 'X' K ROT PUT     @ X(K)=X0-D          UNTIL             ABS T \<=             'M' DECR NOT             OR          END          @ output X(K)          X K GET "Root" \->TAG          @ restore flag settings          flags STOF       \>>    \>> \>>``` RE: Need help with RPL Listing for "SOLVER FOR ANY VARIABLE" - Namir - 07-12-2019 03:55 PM David, Thanks for your good work. This one looks better. Namir