Example of MISO solver for WP 34s
05-22-2018, 09:29 AM (This post was last modified: 05-22-2018 10:06 AM by gomefun2.)
Post: #1
 gomefun2 Junior Member Posts: 25 Joined: May 2018
Example of MISO solver for WP 34s
I will show an example of how to program a MISO (multiple input single output) solver mapped to a single button press for an equation. This is a MISO solver meaning that each time the program is run a different variable can be solved for, without having to rewrite the equation. This program will have named variables.

The equation the program will solve is Darcy's equation for Steady-State Flow. This is equation 6.4 on page 6.3 at http://infohost.nmt.edu/~petro/faculty/E...idflow.pdf

This is a 10 variable equation, with a worked example (at the link) so you can test the code to see if it worked for you.

70 LINES (71 LINES including the final END)

(NOTE: I use // for commenting the code)

LBL A //using this label assigns the program to the physical 'A button' on the calculator
CLα // clears the alpha registry
1 // puts 1 in the x registry
STO 00 // stores 1 into R00. R00's only purpose is to act as a pointer to the memory location. storing 1 into R00 means that R00 will point to the registry R01 (see below for example).
α's' // alpha's' puts s into the alpha registry
XEQ'VAR' // calls and executes the code at LBL'VAR'
α'Pe' // alpha'Pe' puts Pe into the alpha registry
XEQ'VAR' // calls and executes the code at LBL'VAR'
α'Pwf' // alpha'Pwf' puts Pwf into the alpha registry
XEQ'VAR' // calls and executes the code at LBL'VAR'
α'q' // alpha'q' puts q into the alpha registry
XEQ'VAR' // calls and executes the code at LBL'VAR'
α'Bo' // alpha'Bo' puts Bo into the alpha registry
XEQ'VAR' // calls and executes the code at LBL'VAR'
α'u' // alpha'u' puts u into the alpha registry
XEQ'VAR' // calls and executes the code at LBL'VAR'
α'k' // alpha'k' puts k into the alpha registry
XEQ'VAR' // calls and executes the code at LBL'VAR'
α'h' // alpha'h' puts h into the alpha registry
XEQ'VAR' // calls and executes the code at LBL'VAR'
α're' // alpha're' puts re into the alpha registry
XEQ'VAR' // calls and executes the code at LBL'VAR'
α'rw' // alpha'rw' puts rw into the alpha registry
XEQ'VAR' // calls and executes the code at LBL'VAR'
RCL 99 // This recalls the location of output variable in memory (see the subfunctions below)
STO 00 // This stores the location from R99 into R00
RTN // End of Main Function

LBL 'SSR' // This is where the Equation is stored
STO->00 // This stores whatever is in the X register to the location that is stored in R00. For example, if R00 contains 2, then the X register is stored to R02. The STO-> is different than STO (-> is for memory address location)
// STO->00 has no impact on the equation. The reason it is used is that it tells the calculator which variable to solve for. Whichever variable appears first after LBL'SSR' is the variable the calculator will solve for. By storing 5 into R00, and calling STO->00 as the first line in the equation, the calculator will store a random number into R05. But since R05 appears first the calculator will also solve for this registry as the unknown. It basically tricks the calculator to solving for any variable in the equation.
RCL 07 // recall k
RCL 08 // recall h
* // multiply them
RCL 02 // recall Pe
RCL 03 // recall Pwf
- // subtract them
* // multiply
#002 // # is for small integers (0-255) this will put the number 2 into the x registry
SDR 001 // shifts the decimal place once to the right turn 2 into 0.2
#141 // puts 141 into the x registry
+ // adds 0.2 and 141 to make 141.2 (the constant in the equation)
RCL 06 // u
* // multiply
RCL 05 // Bo
* // multiply
RCL 09 // re
RCL 10 // rw
/ // divide
LN // natural logarithm
RCL 01 // s
* // multiply
/ // divide
RCL 04 // q
- // subtract (for the solver to work the equation must be equal to zero (f(x) = 0), so I subtracted q from both sides)
RTN // End of the equation sub-function

LBL'VAR' // The purpose of this subfunction is to help save space when storing data to registers (these are repetive steps).
α'?' // alpha'?' adds a question mark to alpha register, this just makes the prompt look nicer
RCL->00 // the -> means this is an address recall. So this line recalls the value stored in the register at the location stored in R00. For example if R00 contains 3, the value stored in R03 is recalled. The purpose of this is to show the user what is currently stored in each variable.
PROMPT // This waits for user input (when running the program, key in a number and push R/S to enter the value)
STO->00 // Similar to RCL->00 above the -> tells the calculator to store the value in the x register to the location stored in R00.
x<0? // this is a test to see if the user input a negative number. The reason this is here is that all the numbers (aside from 's' in the equation must be positive. If a number is an input as negative then this tells the calculator to solve for that variable. It is just a way I decided to trick the calculator to solve for the correct variable. Since S can be negative I put it first, therefore the calculator will only solve for s (even if it is negative) only if all other variables are positive). x<0? is a conditional statement, if true, it will execute the next line of code, if false it will skip the next line of code.
XEQ'UNK' // this line executes only if the user puts a negative number in for the current variable. This function stores which variable is the one that should be solved for.
INC 00 // this increments R00, this puts a new value into R00, and since R00 is being used as the address locations in the memory this will increment the memory location to the next location. For example, if the program just stored a value into R02, this will increment the program so that the next iteration of the program will store a value into R03.
CLα // Clears the alpha registry
RTN // Ends the subfunction returns to the entry point in the main function

LBL'UNK' // This subfunction stores into memory the variable that should be solved for.
RCL 00 // Recalls the memory location stored in R00
STO 99 // Stores the location to R99. Since s is the first variable in the code, even if it is negative, the next iteration with a negative number (the one that actually wants to be solved for) will store its value here overtop the location of s. (s is the only number that could naturally be negative). s is only solved for if it is the only negative number.
RTN // ends the subfunction
END // Final End

This code could probably be modified slightly to make a general purpose MISO solver. I might end up writing that code next.

At any rate if anyone has a better way to do this code please let me know. I hope this helps at least one other person because it took me a while to figure this out. Thanks to Dieter on the forum for helping, and also the WP 34s manual.

(NOTE: if it isn't clear from the code, the calculator solves for the variable whose initial guess is negative, since these variables are not naturally negative. That is how it decides).
05-22-2018, 05:40 PM (This post was last modified: 05-22-2018 05:41 PM by Dieter.)
Post: #2
 Dieter Senior Member Posts: 2,397 Joined: Dec 2013
RE: Example of MISO solver for WP 34s
(05-22-2018 09:29 AM)gomefun2 Wrote:  I will show an example of how to program a MISO (multiple input single output) solver mapped to a single button press for an equation.

I'll be glad to look at the program and see how it can be improved, but...
sorry, in my humble opinion this is completely unreadable.

There is no need to comment each and every line. If there is a line with a "+" it is not required to explain this is an addition, or if there is a "1" noone needs to know that this puts a "1" into X. This is obvious, so please comment only the essential things. For instance you could add the equation that is solved here.

Maybe you can provide a new listing, completely uncommented, and with a fixed-width font. Try the "code" box in the message editor. Maybe you can also add line numbers so that everyone who wants to comment on a specific piece of code can do so by referring to the respective line number. Here's a tip: type the program in Excel, add the line numbers in the column left of the code and then copy the result.

I hope you do not mind these suggestions, but the way it is now the program is extremely hard to oversee and understand. The pure listing – along with a few explanations after (!) the code – would be very helpful.

Edit: Ok, Ok, I did it myself:

Code:
001  LBL A 002  CLα 003  1 004  STO 00 005  α's' 006  XEQ'VAR' 007  α'Pe' 008  XEQ'VAR' 009  α'Pwf' 010  XEQ'VAR' 011  α'q' 012  XEQ'VAR' 013  α'Bo' 014  XEQ'VAR' 015  α'u' 016  XEQ'VAR' 017  α'k' 018  XEQ'VAR' 019  α'h' 020  XEQ'VAR' 021  α're' 022  XEQ'VAR' 023  α'rw' 024  XEQ'VAR' 025  RCL 99 026  STO 00 027  SLV'SSR' 028  RTN 029  LBL 'SSR' 030  STO->00 031  RCL 07 032  RCL 08 033  * 034  RCL 02 035  RCL 03 036  - 037  * 038  #002 039  SDR 001 040  #141 041  + 042  RCL 06 043  * 044  RCL 05 045  * 046  RCL 09 047  RCL 10 048  / 049  LN 050  RCL 01 051  + 052  * 053  / 054  RCL 04 055  - 056  RTN 057  LBL'VAR' 058  α'?' 059  RCL->00 060  PROMPT 061  STO->00 062  x<0? 063  XEQ'UNK' 064  INC 00 065  CLα 066  RTN 067  LBL'UNK' 068  RCL 00 069  STO 99 070  RTN

By the way: SLV works as a test. If no solution is found the next line is skipped! This way you can add your own error handler.
And SLV expects two initial guesses in X and Y. How does your program handle this?

Dieter
05-22-2018, 07:43 PM (This post was last modified: 05-22-2018 10:08 PM by Dieter.)
Post: #3
 Dieter Senior Member Posts: 2,397 Joined: Dec 2013
RE: Example of MISO solver for WP 34s
(05-22-2018 09:29 AM)gomefun2 Wrote:  I will show an example of how to program a MISO (multiple input single output) solver mapped to a single button press for an equation.
...
At any rate if anyone has a better way to do this code please let me know.

OK, here is my very first, almost untested version, so try it at your own risk ;-)

Code:
001 LBL A 002 CLα 003 # 001 004 STO J 005 CLx 006 STO K 007 α'S' 008 XEQ 99 009 α'Pe' 010 XEQ 99 011 α'Pwf' 012 XEQ 99 013 α'q' 014 XEQ 99 015 α'Bo' 016 XEQ 99 017 α'μ' 018 XEQ 99 019 α'k' 020 XEQ 99 021 α'h' 022 XEQ 99 023 α'Re' 024 XEQ 99 025 α'Rw' 026 XEQ 99 027 RCL K 028 x≥1? 029 GTO 00 030 CLα 031 α'Sel' 032 α'ect' 033 α' Va' 034 α'r !' 035 VIEWα 036 PSE 20 037 GTO A 038 LBL 00 039 STO J 040 # 1/2 041 # 200 042 SLV'SSR' 043 SKIP 001 044 ERR 20 045 RTN 046 LBL 99 047 α'=?' 048 RCL→J 049 PROMPT 050 STO→J 051 x≥0? 052 SKIP 002 053 RCL J 054 STO K 055 INC J 056 CLα 057 RTN 058 LBL'SSR' 059 STO→J 060 RCL 07 061 RCL× 08 062 RCL 02 063 RCL- 03 064 × 065 # 002 066 SDR 001 067 # 141 068 + 069 RCL× 06 070 RCL× 05 071 RCL 09 072 RCL/ 10 073 LN 074 RCL+ 01 075 × 076 / 077 RCL- 04 078 RTN

Some remarks:
• Instead of R00 and R99 (who knows if R99 even exists?) the program uses the J and K registers which are always available. The variable to be solved is stored in K. It is initialized with zero to make sure the user has selected one of the variables as the one to solve for (cf. next point).
Note: J and K are also used for the parameters of some statistical distributions. So if these are involved you should change J and K to, say, A and B. In this case be sure to start the program with a SSIZE4 command as A and B hold the upper (5th and 6th) stack levels in SSIZE8 mode.
• The program checks if the user has selected a variable to solve for (cf. line 028). If not, a respective message is displayed and the input routine starts over.
• Instead of LBL"VAR" the program uses LBL 99 for the input routine. That's much faster to enter. Don't know if this even saves some bytes.
• I have renamed some variables. The 34s character set includes a µ (switch to lower case and press g(reek) M). Even subscripts are available (though not used here).
• The clumsy UNK routine was removed completely. If the user has entered a non-negative variable the program simply skips over the two lines that store the index of the solver variable.
• The implemented equation uses RCL-arithmetics which makes it shorter and more effective. Also the equation was moved to the end of the program.
• If no root is found an error message appears (ERR 20). Yes, the 34s has a set of predefined messages (MSG) and errors (ERR) that are quite handy in such cases.
• The solver needs two initial guesses in X and Y. Since the typical values for the variables may vary by some orders of magnitude I've simply set 0,5 and 200 (cf. line 040/041). This definitely is ..."sub-standard". Better ideas: ask the user for two guesses, or arrange the variables in two groups (say, typically less than 10 or more than 10) and derive a guess from the index of the variable to solve for.

Edit: here's an even better idea. The user enters the solver variable with negative sign to indicate that this is the one to solve for. So simply have the user enter a (negative) guess for this variable. Then start the solver with half and twice that (absolute) value. Example: you want to solve for a variable that should be somewhere near 100. So enter –100 at the respective prompt and the solver will start with 50 and 200. Could this be a good idea? I tried it and it seems to work very well.

I tried the formula in the PDF and solved for q first (result: q=1120,966). Then I changed q to 1000 and solved for µ which was then returned as µ=0,6105.

So far for the moment. ;-)

Dieter
05-23-2018, 05:47 PM (This post was last modified: 05-24-2018 02:35 PM by burkhard.)
Post: #4
 burkhard Senior Member Posts: 359 Joined: Nov 2017
RE: Example of MISO solver for WP 34s
I had a little fun keying this (the original version) in on my lunch break and figuring out the syntax to get some of the characters to appear. Fortunately I purchased the WP-34s manual :-)

1. Nice job! Thanks for including the PDF ref with the example with numbers given. That made a nice check that everything went in OK. I'd like to see more programs that demonstrate the ropes of WP34s programming capability. It is really a pretty handy *small* calculator.
2. I had heard the acronym MISO before, but didn't know the meaning. I understand now and can appreciate the usefulness of being able to solve for any one of the variables. I also like that it can be run repeatedly in sequence, each time retaining the prior inputs as defaults.
3. Your using a negative number as a flag to mean ""Solve for me!" was clever and sensible for this specific example. One can't get away with that always, though...
4. While I agree with Dieter that one doesn't need to comment a simple addition operation, a lot of the comments within "VAR" and "SSR" subroutines were pretty useful and appreciated. Perhaps they aren't needed for an experienced master of keystroke programming, but they were helpful to me. Completely stripping them all out would be a loss. Maybe put them below the code as footnotes by step number so they can be referenced only if needed?
5. Monospaced font was a lot easier to read :-)

Thanks again!
05-23-2018, 07:36 PM
Post: #5
 Dieter Senior Member Posts: 2,397 Joined: Dec 2013
RE: Example of MISO solver for WP 34s
(05-23-2018 05:47 PM)burkhard Wrote:  3. Your using a negative number as a flag to mean ""Solve for me!" was clever and sensible for this specific example. One can't get away with that always, though...

I just noticed that even in the given example equation one of the variables (S) may be negative. So there has to be a workaround. The original program prompts for S as the first variable, and when the solver starts it does not check if a negative value has been entered (instead it solves for S). This is a possible solution for this particular case. My program version (which checks if the user has selected a variable) can not handle negative S values. It assumes that all data is non-negative.

So there should be a better solution for flagging the variable to solve for. I have been thinking about several methods, but none is really convincing. Maybe someone has a better idea?

Dieter
05-23-2018, 09:57 PM
Post: #6
 gomefun2 Junior Member Posts: 25 Joined: May 2018
RE: Example of MISO solver for WP 34s
I will take a look at these suggestions, just super busy until the weekend this week. Thanks.
05-24-2018, 06:17 PM (This post was last modified: 05-24-2018 06:59 PM by Dieter.)
Post: #7
 Dieter Senior Member Posts: 2,397 Joined: Dec 2013
RE: Example of MISO solver for WP 34s
(05-23-2018 07:36 PM)Dieter Wrote:  So there should be a better solution for flagging the variable to solve for. I have been thinking about several methods, but none is really convincing. Maybe someone has a better idea?

If the input can be essentially ...anything, there are two basic methods:

- At the input prompt, press a key like B or C to continue at a different position in the program. This sounds nice ("simply press B at the input prompt when this is the variable you want to solve for"), but it will not work here as it pops the return stack. So the next RTN will not return from the pending subroutine call (LBL 99 or "VAR") to continue with the next variable input, instead the program will simply stop. However, this can be fixed by changing the XEQ calls into GTOs and then jump back to the next variable input with a GTO→J. Of course this requires ten additional labels 01...10. If you want to give it a try, here is the code. Press B when the variable to solve for shows up.

Code:
001 LBL A 002 CLx 003 STO J 004 STO K 005 CLα 006 α'S' 007 GTO 99 008 LBL 01 009 α'Pe' 010 GTO 99 011 LBL 02 012 α'Pwf' 013 GTO 99 014 LBL 03 015 α'q' 016 GTO 99 017 LBL 04 018 α'Bo' 019 GTO 99 020 LBL 05 021 α'μ' 022 GTO 99 023 LBL 06 024 α'k' 025 GTO 99 026 LBL 07 027 α'h' 028 GTO 99 029 LBL 08 030 α'Re' 031 GTO 99 032 LBL 09 033 α'Rw' 034 GTO 99 035 LBL 10 036 RCL K 037 x≥1? 038 GTO 00 039 CLα 040 α'Sel' 041 α'ect' 042 α' Va' 043 α'r !' 044 VIEWα 045 PSE 20 046 GTO A 047 LBL 00 048 STO J 049 # 1/2 050 RCL×→J 051 # 002 052 RCL×→J 053 SLV'SSR' 054 SKIP 001 055 ERR 20 056 RTN 057 LBL 99 058 INC J 059 α'=?' 060 RCL→J 061 PROMPT 062 SKIP 004 063 LBL B 064 RCL J 065 STO K 066 R↓ 067 STO→J 068 CLα 069 GTO→J 070 LBL'SSR' 071 STO→J 072 RCL 07 073 RCL× 08 074 RCL 02 075 RCL- 03 076 × 077 # 002 078 SDR 001 079 # 141 080 + 081 RCL× 06 082 RCL× 05 083 RCL 09 084 RCL/ 10 085 LN 086 RCL+ 01 087 × 088 / 089 RCL- 04 090 RTN

- Use a flag. That's what the next version does. Here the program expects the user to set flag A when the prompt for the variable to solve for appears (press SF A). This turns on the big "=" sign in the display, so there is a visual feedback.

Here is the code:

Code:
001 LBL A 002 CLx 003 STO J 004 STO K 005 CLα 006 α'S' 007 XEQ 99 008 α'Pe' 009 XEQ 99 010 α'Pwf' 011 XEQ 99 012 α'q' 013 XEQ 99 014 α'Bo' 015 XEQ 99 016 α'μ' 017 XEQ 99 018 α'k' 019 XEQ 99 020 α'h' 021 XEQ 99 022 α'Re' 023 XEQ 99 024 α'Rw' 025 XEQ 99 026 RCL K 027 x≥1? 028 GTO 00 029 CLα 030 α'Sel' 031 α'ect' 032 α' Va' 033 α'r !' 034 VIEWα 035 PSE 20 036 GTO A 037 LBL 00 038 STO J 039 # 1/2 040 RCL×→J 041 # 002 042 RCL×→J 043 SLV'SSR' 044 SKIP 001 045 ERR 20 046 RTN 047 LBL 99 048 INC J 049 CF A 050 α'=?' 051 RCL→J 052 PROMPT 053 STO→J 054 RCL J 055 FS?C A 056 STO K 057 CLα 058 RTN 059 LBL'SSR' 060 STO→J 061 RCL 07 062 RCL× 08 063 RCL 02 064 RCL- 03 065 × 066 # 002 067 SDR 001 068 # 141 069 + 070 RCL× 06 071 RCL× 05 072 RCL 09 073 RCL/ 10 074 LN 075 RCL+ 01 076 × 077 / 078 RCL- 04 079 RTN

In both cases the program also takes the input at this prompt as an estimate for the solution. It feeds 1/2x and 2x this value as the two initial guesses into the solver. So if you enter 100 the first two guesses are 50 and 200. Adjust this as you like with the two factors in line 049/051 or 039/041, respectively.

Now try it and see if this works for you. ;-)

Dieter
 « Next Oldest | Next Newest »

User(s) browsing this thread: 1 Guest(s)