Post Reply 
Creating an equation library (Updated 03-FEB-2017)
11-14-2015, 02:50 AM (This post was last modified: 11-14-2015 02:50 AM by Han.)
Post: #41
RE: Creating an equation library (updated)
(11-14-2015 02:24 AM)Helge Gabert Wrote:  So, in order to obtain the same DOT() result in CAS as in Home,

in CAS only,

one has to call DOT(CONJ([vector_1]),[vector_2]);

with complex elements in vector_1, in order to negate the complex conjugates which otherwise arise. A bug?

Well, the CAS dot product is the "more correct" dot product for both real and complex vectors since the dot product of a vector with itself is generally considered to be the square of the norm of the vector (and this quantity is a real number, not complex). If a vector \( v \) is complex, the only way to guarantee a real-valued inner product of \( v \) with itself is to define
\[ \langle v, v \rangle = v^H \cdot v \]
where \( v^H \) is the Hermitian transpose (conjugate transpose) and \( v \) is assumed to be in "column" form. What I find amusing is that the ABS(v) command works the same in Home or CAS, whether the vector \( v \) is complex or real -- and the result is actually the square root of \( v^H \cdot v \) in the case where \( v \) is complex. I am not sure why the DOT() command in Home does not work the same way as dot() in CAS view.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
11-14-2015, 03:30 AM
Post: #42
RE: Creating an equation library (updated)
I see your reasoning, but look at Wolfram Alpha, for example

dot([2+i,i],[9-i,7]) returns 19+14*i, just like it does in Home.

http://www.wolframalpha.com/input/?i=dot...%2C7%5D%29
Find all posts by this user
Quote this message in a reply
11-14-2015, 05:25 AM
Post: #43
RE: Creating an equation library (updated)
(11-14-2015 03:30 AM)Helge Gabert Wrote:  I see your reasoning, but look at Wolfram Alpha, for example

dot([2+i,i],[9-i,7]) returns 19+14*i, just like it does in Home.

http://www.wolframalpha.com/input/?i=dot...%2C7%5D%29

I suppose if we were to be truly technical, then both the Prime and Wolfram would be incorrect in allowing vectors that are not real-valued since the "dot product" (being a special type of inner product) is for finite Euclidean spaces. Both Maple and Matlab disagree with Wolfram Alpha; their "dot" product uses the Hermitian inner product if the vectors are complex.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
11-14-2015, 05:51 AM (This post was last modified: 11-14-2015 05:51 AM by Helge Gabert.)
Post: #44
RE: Creating an equation library (updated)
OK, that is true, and open source platforms such as Octave (similar to Matlab) also return the hermitian inner product (in this example 17-18*i).
Find all posts by this user
Quote this message in a reply
04-23-2016, 04:50 PM
Post: #45
RE: Creating an equation library (updated)
I´ve checked this software in new firmware (10077), and after equation list, and press OK, a syntax error appears.
Find all posts by this user
Quote this message in a reply
01-27-2017, 05:47 PM
Post: #46
RE: Creating an equation library (updated)
Nothing like a nearly-year-long delay between a post and a response... but I finally had some time to get back to this project. This time, however, I am approaching it from the "other end" (i.e. interface).

Since we now have access to app files and app variables, it is easier (not really) to manage equations and variables from a programmer's point of view. The code below does nothing other than create an app for us to create systems of equations and save it in a library.

If you copy the buit-in Solve app, and paste the code below into the copied app (I called it Equation Library, but you can use whatever name you want), then it should be ready to go. The app starts off by looking for an app file named "Equation Library.lib" which is supposed to be a list containing different systems of equations. If you don't have such a file, it will make one for you. Each system is itself a list consisting of a name, equations, variables, and the descriptions of the variables. You can use the [View] key to get more options such as adding another page of equations (since the Symb view only shows 10 at a time).

To create a new system, start by creating your variables. Press [View] and select Add/Edit variables. Enter in a variable name and a description for the variable. Once your variables are created, you can start creating your equations. Save your system using [View]. Missing features are deletion (of variables, and of systems); that will come once we build a UI for browsing the list of systems.

I am hoping to finally put everything together (the solver engine) so that this becomes a full blown equation library complete with solver and "file manager" to manage your various systems.

In the meantime, people can play around with the code below if they want to start building their libraries. For those who do not speak English, the code is prepared in a way that should easily port to other languages (all the text are at the top of the source with the only exceptions being the [View] menu options).

PHP Code:
ssVersion:="Equation Library 0.01 by Han Duong";

// colors
ssFG:=#0h;
ssBG:=#FFFFFFh;
ssR:=#FF0000h;
ssG:=#FF00h;
ssB:=#FFh;


// error messages
ssInvDat:="Invalid library data.";
ssNoDat:="Unable to locate library data.";
ssNullName:="Null name not allowed.";
ssInvName:="Invalid name.";
ssAbort:="Operation aborted; improper initialization.";
ssBadVar:="Conflict with existing variable:\n";
ssSubmitBug:="This should never happen!\nPLease submit bug report.";
ssNotEqn:="Non-equation on page ";
ssNonVar:="No such var. on page ";
ssNoLibDat:="No library data found.\nCreating empty library and empty\ninitial system.";
ssEOW:="Overwrite disabled and name already exists:\n";
ssNotSaved:="SAVE CANCELED!";


// app messages
ssTNewVar:="Create/Edit Variable";
ssLName:="Name:";
ssLDescr:="Description:";
ssLOWrite:="Overwrite";
ssHName:="Enter the variable name";
ssHDescr:="Enter a description for the variable";
ssHOWrite:="Overwrite if variable already exists?";
ssTSaveSys:="Save Current System";
ssHSysName:="Enter a name for the system.";
ssLEqns:="Eqns:";
ssLVars:="Vars:";
ssHEqns:="Verify equations in system.";
ssHVars:="Verify variables for system.";
ssTNewSys:="New System";

ssTSettings:="Equation Library Settings";
ssLSaving:="When switching systems, always";
ssCSaving:={ "prompt to save""save automatically""discard all changes"};
ssHSaving:="Select default save behavior";


// misc
ssVLoadEqns:="Populating equations in Symb view...";
ssVLoadVars:="Setting up equation variables...";
ssVCheckVars:="Verifying variables in system...";
ssVCheckLibDat:="Verifying library data...";
ssVUpdateEqns:="Equations modified; updating lib data...";
ssVUpdateVars:="Variables modified; updating lib data...";
ssVNoEqns:="(No equations)";
ssVNoVars:="(No variables)";
ssVVarMade:="Created variable: ";


// View menu options
ssTSEP:="Select Equations Page";
ssTSelPage:="Select New Page";
ssTNewPage:="Create New Page";


ssMsgRow;
export ssInit;
ssLibFN;
export ssCurSys;
export ssCurSysIndex;
export ssCurLib;
ssLibSize;
export ssSysTitles;
ssVarKey:="SSVersion";
export ssEqPages;
export ssEqPage;
export ssNullSys;


// DO NOT MODIFY BELOW HERE

ssUpdateSys()
begin
  local n
;
  
local eq:="";
//  for n from 0 to 9 do
//    eq:="E" + string(n,1,0) + ":=" + string("");
//    expr(eq);
//  end;
  
if ssLibSize then
    ssSysTitles
:=makelist(ssCurLib(I,1),I,1,ssLibSize);
  else
    
ssSysTitles:={};
  
end;
  
ssEqPages:={1,10};
  
n:=size(ssCurSys(2));
  
ssNullSys:=NOT(n);
  
ssEqPages(1):=ip((n-1)/10);
  
ssEqPages(2):=(n-1mod 10;
  
ssEqPage:=0;
  
DelAVars(AVars);
end;



ssInitSSApp()
begin
  
if ssInit then return; end;

  
ssLibFN:="Equation Library.lib";
  
ssVarKey:="SSVersion";
  
iferr
    ssCurLib
:=AFiles(ssLibFN);
  
then
    msgbox
(ssNoLibDat);
    
ssCurLib:={ { ssTNewSys, {}, {}, {}, {}, {}, {} } };
    
AFiles(ssLibFN):=ssCurLib;
  
end;
  
ssCurSysIndex:=1;
  
ssCurSys:=ssCurLib(1);
  
ssLibSize:=size(ssCurLib);
  
ssUpdateSys();
  
ssInit:=1;
end;


ssPrint(msg)
begin
  textout_p
(msg,0,10*ssMsgRow,1,ssFG,320,ssBG);
  
ssMsgRow:=(ssMsgRow+1mod 20;
end;


ssError(msg)
begin
  textout_p
(msg,0,10*ssMsgRow,1,ssR,320,ssBG);
  
ssMsgRow:=(ssMsgRow+1mod 20;
end;


ssCheckType(list,t)
begin
  local n
:=size(list);
  if 
n then
    
if type(list(n))<>t then return(1); end;
  else
    return(
1);
  
end;
  return(
0);
end;



//******************************************
// Library Data format
// { sys1, sys2, ... , sysN }
//
// Each sys (system) is a list of the form
// {
//   "Title",
//   { "eq1", "eq2", ... },
//   { sel1, sel2, ... },
//   { "var1", "var2", ... },
//   { "des1", "des2", ... },
//   { val1, val2, ... },
//   { con1, con2, ... }
// }
//
// eq  = equation
// sel = 0 or 1 for selection of corresponding
//       equation in the system
// var = variable
// des = description of variable
// val = value of corresponding variable
// con = 0 or 1 for whether var is constant
//
// returns 0 if error or 1 if OK
//******************************************
export ssCheckLibDat()
begin

  ssPrint
(ssVCheckLibDat);
  
ssInitSSApp();

  
local syseqs,j,k;
  
local libisbad:=0;
  
local types:={2,2,0,2,2,0,0};

  
iferr
    
if ssLibSize then
      
for j from 1 to ssLibSize do
        
lib:=ssCurLib(j);
        if 
type(lib)<>6 then
          ssError
(ssInvDat); return(0);
        else
          
k:=size(lib);
          if (
k<1) OR (k>7then
            ssError
(ssInvDat); return(0);
          
end;
          for 
k from 2 to 7 do
            if 
type(lib(k))<>6 then
              ssError
(ssInvDat); return(0);
            
end;
            if 
ssCheckType(lib(k),types(k)) then
              ssError
(ssInvDat); return(0);
            
end;
          
end// for k
        
end// if type(lib)
      
end// for j
    
end// if ssLibSize
  
then
    ssError
(ssNoDat); return(0);
  
end;
  return(
1);
end;


// initialize variables
ssInitVars()
begin

  local varslist
:=ssCurSys(4);
  
local valslist:=ssCurSys(6);
  
local n:=size(varslist);
  
local j,tmp,varval;


  
iferr
    
if (AVars(ssVarKey) == ssVersionthen   
      
return;
    
end;
  
then
    
// nop
  
end;

  
ssPrint(ssVLoadVars);
  for 
j from 1 to n do
    
varval:=CAS(eval(varslist(j)));
    
tmp:="purge(" varslist(j) + ")";
    
CAS(eval(tmp));
    if (
CAS(eval(varslist(j))) <> 8then
      msgbox
(ssBadVar+varslist(j));
    
end;
    if ( (
type(varval) == 0) OR (type(varval) == 3) ) then
      AVars
(varslist(j)):=varval;
    else
      
AVars(varslist(j)):=valslist(j);
    
end;
  
end;
  
AVars(ssVarKey):=ssVersion;

end;


// checks to see if AVars and system of equations
// vars match; excludes version key
export ssCheckVars()
begin

  ssPrint
(ssVCheckVars);
  
ssInitSSApp();
  
ssInitVars();

  
local j,n;
  
local avarlist:=AVars();
  
local varlist:=ssCurSys(4);
  
n:=size(varlist);
  if (
n+<> size(avarlist)) then
    
return(0);
  
end;

  for 
j from 1 to n do
    if (
pos(avarlist,varlist(j)) == 0then return(0); end;
  
end;

  
n:=size(avarlist);
  for 
j from 1 to n do
    if ((
avarlist(j) <> ssVarKey) AND (pos(varlist,avarlist(j)) == 0)) then
      
return(0);
    
end;
  
end;
  return(
1);

end;


// do we have any equations
//  1: yes, equations in symb view
//  0: no equations at all
// -1: yes, but only saved in library
ssHaveEqns()
begin
  local j
;
  for 
j from 0 to 9 do
    if 
ISCHECK(jthen return(1); end;
  
end;

  if (
ssCurSysIndex == 0then return(0); end;

  if (
type(ssCurSys) <> 6then return(0); end;

  if 
size(ssCurSysthen
    
if size(ssCurSys(2)) then
      
return(-1);
    else
      return(
0);
    
end;
  else
    return(
0);
  
end;
end;


// UI for creating new variables
ssCreateVar()
begin
  local run
:=1;
  
local n;
  
local varname:=""varinfo:="";
  
local ow:=0;

  
ssInitSSApp();
  
ssInitVars();

  while 
run do
    if 
input(
      {
        {
varname, [2], {30650}},
        {
varinfo, [2], {30651}},
        {
ow1, {30,10,2}}
      },
      
ssTNewVar,
      { 
ssLNamessLDescrssLOWrite },
      { 
ssHNamessHDescrssHOWrite }
    )
    
then

      
if size(varname)<1 then
        msgbox
(ssNullName);
      else
        
n:=pos(AVars,varname);
        if 
n then
          
if ow then
            n
:=pos(ssCurSys(4),varname);
            
ssCurSys(5,n):=varinfo;
            
run:=0;
          else
            
msgbox(ssEOW varname);
          
end;
        else
          
iferr 
            AVars
(varname):=0;
          
then
            msgbox
(ssInvName);
          else
            
ssCurSys(4,0):=varname;
            
ssCurSys(5,0):=varinfo;
            
ssCurSys(6,0):=0;
            
ssCurSys(7,0):=0;
            
msgbox(ssVVarMade varname);
            
varname:=""varinfo:="";
//            run:=0;
          
end;
        
end;
      
end// end null name

    
else
      
run:=0;
    
end;

  
end// end while
end;


// save current equations
ssSaveEqns()
begin
  local j
,k,n1,n2;
  
local cmd:="";
  
local oldeqn:="";
  
local neweqn:="";
  
local markadd:=0;
  
local neweqns:={};
  
local teqnlist:={};
  
local tsellist:={};

  if 
ssCheckVars() then

    ssPrint
(ssVLoadEqns);
    
n1:=ssEqPage*10+1;
    if (
ssEqPage ssEqPages(1)) then
      n2
:=n1+9;
    else
      
n2:=n1+ssEqPages(2);
    
end;

    for 
j from n1 to n2 do
      
k:= j mod 10;
      
cmd:="string(E" string(k,1,0) + ",1,12)";

      
iferr
        neweqn
:=expr(cmd);
      
then
        neweqn
:="";
      else
        if 
ssNullSys then
          oldeqn
:="";
        else
          
cmd:="E" string(k,1,0) + ":=" string(ssCurSys(2,j));
          
iferr expr(cmd); then end;
          
cmd:="string(E" string(k,1,0) + ",1,12)";
          
iferr oldeqn:=expr(cmd); then end;
        
end;
        if (
oldeqn <> neweqnthen
          
if ssNullSys then
            ssCurSys
(2,0):=neweqn;
          else
            
ssCurSys(2,j):=neweqn;
          
end;
        
end;
      
end;

      
cmd:="E" string(k,1,0) + ":=" string(neweqn);
      
iferr expr(cmd); then
        
// msgbox(ssSubmitBug);
      
end;

      if 
ISCHECK(kthen
        ssCurSys
(3,j):=1;
      else
        
ssCurSys(3,j):=0;
      
end;

      if (
size(neweqn) == 0then
        ssCurSys
(3,j):=-1// mark for delete
      
end;
    
end;  // end for j

    
n2:=n1+9;
    for 
k from j to n2 do
      
n1:=k mod 10;
      
cmd:="string(E" string(n1,1,0) + ",1,12)";
      
iferr
        neweqn
:=expr(cmd);
      
then
        
// nop
      
else
        if 
size(neweqnthen
          neweqns
(0):=neweqn;
          
neweqns(0):=ISCHECK(n1);
          
markadd:=1;
        
end;
      
end;
    
end// end for k

    // rebuilt existing equations
    
k:=0;
    
n2:=size(ssCurSys(2));
    for 
j from 1 to n2 do
      if (
ssCurSys(3,j) >= 0then
        teqnlist
(0):=ssCurSys(2,j);
        
tsellist(0):=ssCurSys(3,j);
        
k:=k+1;
      
end;
    
end;
    
ssCurSys(2):=teqnlist;
    
ssCurSys(3):=tsellist;

    if 
markadd then
      n2
:=size(neweqns)/2;
      for 
j from 1 to n2 do
        
ssCurSys(2,0):=neweqns(2*j-1);
        
ssCurSys(3,0):=neweqns(2*j);
        
k:=k+1;
      
end;
    
end;

    
ssEqPages(1):=ip((k-1)/10);
    
ssEqPages(2):=(k-1mod 10;
    
ssEqPage:=min(max(0,ssEqPage),ssEqPages(1));

    if 
k then
      ssNullSys
:=0;
    else
      
ssNullSys:=1;
    
end;

    return(
1);

  else
    
msgbox(ssAbort);
    return(
0);
  
end;
end;


// set up equations in Symb view
export ssLoadSymb()
begin

  local j
,k,n1,n2;
  
local cmd:="";

  
// no equations to populate Symb view?
  
if ssNullSys then 
    
for j from 0 to 9 do
      
cmd:="E" string(j,1,0) + ":=" string("");
      
expr(cmd);
    
end;
    return(
1);
  
end;

  
ssPrint(ssVLoadEqns);
  
n1:=ssEqPage*10+1;
  if (
ssEqPage ssEqPages(1)) then
    n2
:=n1+9;
  else
    
n2:=n1+ssEqPages(2);
  
end;
  for 
j from n1 to n2 do
    
k:= j mod 10;
    
cmd:="E" string(k,1,0) + ":=" string(ssCurSys(2,j));
    
iferr expr(cmd); then end;
    if (
ssCurSys(3,j)==1then CHECK(k); else UNCHECK(k); end;
  
end;

  
n2:=n1+9;
  for 
k from j to n2 do
    
n1:=k mod 10;
    
cmd:="E" string(n1,1,0) + ":=" string("");
    
expr(cmd);
  
end;

  return(
1);

end;


// select an equations page
ssSelectEqPage()
begin
  ssInitSSApp
();
  
local j;
  
local n:=ssEqPages(1)+1;
  
local page:=ssEqPage+1;
  
local curpage:=page;
  
local pagelist:={};
  
local title:="[" string(page,1,0) + "/" string(ssEqPages(1)+1,1,0) + "] " ssTSelPage;
  
  
pagelist:=makelist(j,j,1,n);
  
pagelist(0):=ssTNewPage;

  if 
choose(page,title,pagelistthen

    
if (curpage <> pagethen
      ssSaveEqns
(); 

      if (
page == (n+1)) then

        
if (ssNullSys == 0then 
          ssEqPages
(1):=n+1;

          
// fill last page
          
if (ssEqPages(2) < 9then
            n
:=9-ssEqPages(2);
            for 
j from 1 to n do
              
ssCurSys(2,0):="";
              
ssCurSys(3,0):=-1// mark for deletion
            
end;
          
end;
        
end;

        
// create new page
        
for j from 1 to 10 do
          
ssCurSys(2,0):="";
          
ssCurSys(3,0):=-1// mark for deletion
        
end;

        
n:=size(ssCurSys(2));
        
ssEqPage:=ip((n-1)/10);
        
ssEqPages(1):=ssEqPage;
        
ssEqPages(2):=(n-1mod 10;
        
ssNullSys:=0;

      else

        
// not creating new blank page
        
ssEqPage:=min(max(0,page-1),ssEqPages(1));

      
end// if newpage or existing page

    
end// if selpage <> page

    
ssLoadSymb();

  
end// if choose
end;


// set new system
export ssSetNewSys(n)
begin
  
if (== ssCurSysIndexthen
    
return(1);
  
end;

  if (
ssLibSizethen
    
return(0);
  
end;

  
ssCurSysIndex:=n;
  
ssCurSys:=ssCurLib(n);
  
ssUpdateSys();
  
ssInitVars();
  
ssLoadSymb();
end;


ssErrorPage(n,msg,eqn)
begin
  local p
:=ip((n-1)/10)+1;
  
msgbox(msg ":\n" eqn);
end;


// check if equations are valid
// assumes equations have been saved
export ssCheckEqns()
begin
  local n
:=size(ssCurSys(2));
  
local eqn:="";
  
local j,k,v;
  
local varlist:={};

  if 
n then

    
// check each equation
    
for j from 1 to n do
      
eqn:=ssCurSys(2,j);

      
// do we have = symbol?
      
if instring(eqn,"="then
        iferr eqn
:=string(E0,1,12); then eqn:=""end;
        
E0:=ssCurSys(2,j);
        
varlist:=LNAME(E0);
        
v:=size(varlist);
        if 
v then
          
for k from 1 to v do
            if (
pos(ssCurSys(4),string(varlist(k))) == 0then
              ssErrorPage
(j,ssNonVar,ssCurSys(2,j)+"\n> "+varlist(k));
              return(
0);
            
end;
          
end;
        else
          
// constants only? not equation
          
ssErrorPage(j,ssNotEqn,ssCurSys(2,j));
          return(
0);       
        
end;
        
iferr E0:=eqnthen end;
        return(
1);
        
      else
        
// no equal symbol; report page
        
ssErrorPage(j,ssNotEqn,eqn);
        return(
0);
      
end;
    
end;

  else
    
// no equations to check
    
return(1);
  
end;
end;


// save current system
// no null names but does not check
// if name is all spaces
ssSaveSystem()
begin
  local sysname
:=ssCurSys(1);
  
local eqns:=ssCurSys(2);
  
local vars:=ssCurSys(4);
  
local eqn,var,n;
  
local run:=1;

  
// bug in input when choose lists are empty
  
if (size(eqns) < 1then eqns:={ ssVNoEqns }; end;
  if (
size(vars) < 1then vars:={ ssVNoVars }; end;


  while 
run do
    if 
input(
      {
        { 
sysname, [2], { 1575} },
        { 
eqneqns, { 1575} },
        { var, 
vars, { 1575} }
      },
      
ssTSaveSys,
      { 
ssLName,    ssLEqnsssLVars },
      { 
ssHSysNamessHEqnsssHVars }
    )
    
then

      
if size(sysnamethen
        
// maybe later add check for dupes
        
n:=pos(ssSysTitlessysname);

        if 
ssCheckEqns() then
          ssCurSys
(1):=sysname;
          
ssCurLib(ssCurSysIndex):=ssCurSys;
          
AFiles(ssLibFN):=ssCurLib;
        else
          
msgbox(ssNotSaved);
        
end;
        
run:=0;

      else
        
msgbox(ssNullName);
      
end;

    else
      
// user canceled
      
msgbox(ssNotSaved);
      
run:=0;
    
end;

  
end// end while;
end;


// create a system
ssNewSystem()
begin
  ssCurSys
:={ssTNewSys, {}, {}, {}, {}, {}, {} };
  
ssCurLib(0):=ssCurSys;
  
ssCurSysIndex:=ssCurSysIndex 1;
  
ssLibSize:=ssLibSize 1;
  
ssUpdateSys();
  
ssInitVars();
  
ssLoadSymb();
  
startview(0,1);
end;



START()
begin
//  startview(-1,1);
  
ssInitSSApp();
  
ssInitVars();
  
ssLoadSymb();
  
startview(0,1);
end;


Symb()
begin
  ssSaveEqns
();
  
ssLoadSymb();
  
startview(0,1);
end;


// select equations page (View Menu)
view "Select Page"ssMenuEqnPage()
begin
  ssSelectEqPage
();
  
startview(0,1);
end;


// UI for creating new variables (View Menu)
view "Add/Edit Variable"ssMenuNewVar()
begin
  ssCreateVar
();
end

// reload saved equations (View Menu)
view "Restore Equations"ssMenuLoadEqns()
begin
  ssLoadSymb
();
  
startview(0,1);
end;


// save current system (View Menu)
view "Save System"ssMenuSaveSys()
begin
  ssSaveEqns
();
  
ssSaveSystem();
end;

// create new system (View Menu)
view "New System"ssMenuNewSys()
begin
  ssNewSystem
();
end

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
01-27-2017, 07:41 PM
Post: #47
RE: Creating an equation library (updated)
Hi Han

1: ISCHECK() Function not found =(

2: To contribute (in my case with Spanish), the messages in a list
[English, French, Spanish, Portuguese]

// app messages
ssTNewVar:="Create/Edit Variable"; ->
ssTNewVar:= [ "Create/Edit Variable", "Créer/Modifier la variable", "Crear/Editar Variable", "Criar/EditarVariável" ];
Find all posts by this user
Quote this message in a reply
01-27-2017, 07:51 PM (This post was last modified: 01-27-2017 08:20 PM by Han.)
Post: #48
RE: Creating an equation library (updated)
(01-27-2017 07:41 PM)compsystems Wrote:  Hi Han

1: ISCHECK() Function not found =(

This would be a firmware issue. ISCHECK() was implemented some time ago, so your issue seems to suggest that you have firmware that is far too old.

Quote:2: To contribute (in my case with Spanish), the messages in a list
[English, French, Spanish, Portuguese]

// app messages
ssTNewVar:="Create/Edit Variable"; ->
ssTNewVar:= [ "Create/Edit Variable", "Créer/Modifier la variable", "Crear/Editar Variable", "Criar/EditarVariável" ];

Once the program is actually out of "Proof of Concept" phase, then the messages will actually be implemented as a single list of strings. Each language will be its own separate list stored in a language file. In fact, variables such as ssTNewVar won't even exist anymore -- they will be converted into something like ssMsg[i] (the i-th messsage) where ssMsg is a list loaded from a language file, and the language is determined by the calculator's Language setting. Users will eventually be able to delete language files they don't need and the app will ask the user to choose from among the available language files if the Language setting in the calculator is not available among the language files.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
01-30-2017, 11:10 PM
Post: #49
RE: Creating an equation library (updated)
Thank you Han, for this improvement. I´ve tested it in another thread with positive results.
Now the bad news. Don´t know why but after calculations, I press the app icon for start the program again, and it restart the calculator. There is some kind of variable stored that corrupt the system. Mu version is the newest on physical calculator. So the first time has worked flawlessly, the second or next, restart.
Find all posts by this user
Quote this message in a reply
01-31-2017, 12:16 AM (This post was last modified: 01-31-2017 08:58 AM by Han.)
Post: #50
RE: Creating an equation library (updated)
Yes, it is likely due to a bug related to input forms (avoid choose lists in input forms if you cannot guarantee that the lists are never empty). I'll be posting an update shortly that provides a workaround and includes part of the solver engine.

EDIT: very basic solver in place (only works on systems whose Jacobian is invertible). Use [View] Menu for managing systems of equations. [Plot] is a hotkey for choosing a system that has been archived. [Num] starts the solver. [NumSetup] provides variable management. (Currently cannot delete variables). Very alpha-ish release. Don't do obvious "no-no" things like trying to solve an empty system of equations.

PHP Code:
ssVersion:="Equation Library 0.05 by Han Duong";

// colors
ssFG:=#0h;
ssBG:=#FFFFFFh;
ssR:=#FF0000h;
ssG:=#FF00h;
ssB:=#FFh;


// error messages
ssInvDat:="Invalid library data.";
ssNoDat:="Unable to locate library data.";
ssNullName:="Null name not allowed.";
ssInvName:="Invalid name.";
ssAbort:="Operation aborted; improper initialization.";
ssBadVar:="Conflict with existing variable:\n";
ssSubmitBug:="This should never happen!\nPLease submit bug report.";
ssNotEqn:="Non-equation on page ";
ssNonVar:="No such var. on page ";
ssNoLibDat:="No library data found.\nCreating empty library and empty\ninitial system.";
ssEOW:="Overwrite disabled and name already exists:\n";
ssNotSaved:="SAVE CANCELED!";
ssMustChoose:="Select a system or create a new one.";
ssNoVars:="No variables for this system!";
ssNoSystems:="No systems in library!";

// app messages
ssTNewVar:="Create/Edit Variable";
ssLName:="Name:";
ssLDescr:="Description:";
ssLOWrite:="Overwrite";
ssHName:="Enter the variable name";
ssHDescr:="Enter a description for the variable";
ssHOWrite:="Overwrite if variable already exists?";
ssTSaveSys:="Save Current System";
ssHSysName:="Enter a name for the system.";
ssLEqns:="Eqns:";
ssLVars:="Vars:";
ssHEqns:="Verify equations in system.";
ssHVars:="Verify variables for system.";
ssTNewSys:="New System";
ssTChooseSys:="Choose a System";
ssHMakeConst:="Make this variable constant?";
ssTDeleteSys:="Select Systems to Delete";
ssHMarkDel:="Mark for deletion?";


ssTSettings:="Equation Library Settings";
ssLSaving:="When switching systems, always";
ssCSaving:={ "prompt to save""save automatically""discard all changes"};
ssHSaving:="Select default save behavior";


// misc
ssVLoadEqns:="Populating equations in Symb view...";
ssVLoadVars:="Setting up equation variables...";
ssVCheckVars:="Verifying variables in system...";
ssVCheckLibDat:="Verifying library data...";
ssVUpdateEqns:="Equations modified; updating lib data...";
ssVUpdateVars:="Variables modified; updating lib data...";
ssVNoEqns:="(No equations)";
ssVNoVars:="(No variables)";
ssVVarMade:="Created variable: ";


// View menu options
ssTSEP:="Select Equations Page";
ssTSelPage:="Select New Page";
ssTNewPage:="Create New Page";


ssMsgRow;
export ssInit;
ssLibFN;
export ssCurSys;
export ssCurSysIndex;
export ssCurLib;
ssLibSize;
export ssSysTitles;
ssVarKey:="SSVersion";
export ssEqPages;
export ssEqPage;
export ssNullSys;
export ssWarning;
export ssSolveVars:={};


// DO NOT MODIFY BELOW HERE

ssGlobal:={ "A""B""C""D""E""F""G",
            
"H""I""J""K""L""M""N",
            
"O""P""R""S""T""U""V",
            
"W""X""Y""Z""θ",
            
"Z0""Z1""Z2""Z3""Z4",
            
"Z5""Z6""Z7""Z8""Z9"
};


ssUpdateSys()
begin
  local n
;

  
ssEqPages:={1,10};
  
n:=size(ssCurSys(2));
  
ssNullSys:=NOT(n);
  
ssEqPages(1):=ip((n-1)/10);
  
ssEqPages(2):=(n-1mod 10;
  
ssEqPage:=0;
  for 
n from 1 to size(ssCurSys(4)) do
    if 
NOT(ssCurSys(7,n)) then ssSolveVars(0):=ssCurSys(4,n); end;
  
end;
  
DelAVars(AVars);
end;


ssInitSSApp()
begin
  local j
,run:=1;
  
local cmd:="";
  if 
ssInit then return; end;

  
dimgrob_p(G1,320,240);

  
ssLibFN:="Equation Library.lib";
  
ssVarKey:="SSVersion";
  
ssWarning:=1;

  
iferr
    ssCurLib
:=AFiles(ssLibFN);
  
then
    msgbox
(ssNoLibDat);
    
ssCurLib:={};
    
AFiles(ssLibFN):=ssCurLib;
  
end;
  for 
j from 0 to 9 do
    
cmd:="E" string(j,1,0) + ":=" string("");
    
expr(cmd);
  
end;
  
// always start app with new system
  
ssCurSys:={ssTNewSys, {}, {}, {}, {}, {}, {} };
  
ssLibSize:=size(ssCurLib);
  if 
ssLibSize then
    ssSysTitles
:=makelist(ssCurLib(j,1),j,1,ssLibSize);
  
end;
  
ssCurSysIndex:=0;
  
ssUpdateSys();
  
ssInit:=1;
end;


ssPrint(msg)
begin
  textout_p
(msg,G1,0,12*ssMsgRow,1,ssFG,320,ssBG);
  
line_p(G1,0,12*ssMsgRow+12,12,12*ssMsgRow+12,ssR);
  
ssMsgRow:=(ssMsgRow+1mod 20;
end;


ssError(msg)
begin
  textout_p
(msg,G1,0,12*ssMsgRow,1,ssR,320,ssBG);
  
line_p(G1,0,12*ssMsgRow+12,12,12*ssMsgRow+12,ssR);
  
ssMsgRow:=(ssMsgRow+1mod 20;
end;

ssWarn(msg)
begin
  
if ssWarning then
    msgbox
(msg);
  
end;
end;


ssCheckType(list,t)
begin
  local n
:=size(list);
  if 
n then
    
if type(list(n))<>t then return(1); end;
  else
    return(
1);
  
end;
  return(
0);
end;



//******************************************
// Library Data format
// { sys1, sys2, ... , sysN }
//
// Each sys (system) is a list of the form
// {
//   "Title",
//   { "eq1", "eq2", ... },
//   { sel1, sel2, ... },
//   { "var1", "var2", ... },
//   { "des1", "des2", ... },
//   { val1, val2, ... },
//   { con1, con2, ... }
// }
//
// eq  = equation
// sel = 0 or 1 for selection of corresponding
//       equation in the system
// var = variable
// des = description of variable
// val = value of corresponding variable
// con = 0 or 1 for whether var is constant
//
// returns 0 if error or 1 if OK
//******************************************
export ssCheckLibDat()
begin

  ssPrint
(ssVCheckLibDat);
  
ssInitSSApp();

  
local syseqs,j,k;
  
local libisbad:=0;
  
local types:={2,2,0,2,2,0,0};

  
iferr
    
if ssLibSize then
      
for j from 1 to ssLibSize do
        
lib:=ssCurLib(j);
        if 
type(lib)<>6 then
          ssError
(ssInvDat); return(0);
        else
          
k:=size(lib);
          if (
k<1) OR (k>7then
            ssError
(ssInvDat); return(0);
          
end;
          for 
k from 2 to 7 do
            if 
type(lib(k))<>6 then
              ssError
(ssInvDat); return(0);
            
end;
            if 
ssCheckType(lib(k),types(k)) then
              ssError
(ssInvDat); return(0);
            
end;
          
end// for k
        
end// if type(lib)
      
end// for j
    
end// if ssLibSize
  
then
    ssError
(ssNoDat); return(0);
  
end;
  return(
1);
end;


// initialize variables
ssInitVars()
begin

  local varslist
:=ssCurSys(4);
  
local valslist:=ssCurSys(6);
  
local n:=size(varslist);
  
local j,varval;


  
iferr
    
if (AVars(ssVarKey) == ssVersionthen   
      
return;
    
end;
  
then
    
// nop
  
end;

  
ssPrint(ssVLoadVars);
  for 
j from 1 to n do
    if 
pos(ssGlobal,varslist(j)) then
      expr
(varslist(j) + ":=" valslist(j));
    else
      
varval:=CAS(EVAL(varslist(j)));
      
purge(EVAL(varslist(j)));
      if (
type(CAS(EVAL(varslist(j)))) <> 8then
        ssWarn
(ssBadVar+varslist(j));
      
end;
      if ( (
type(varval) == 0) OR (type(varval) == 3) ) then
        AVars
(varslist(j)):=varval;
      else
        
AVars(varslist(j)):=valslist(j);
      
end;
    
end;
  
end;
  
AVars(ssVarKey):=ssVersion;

end;


// checks to see if AVars and system of equations
// vars match; excludes version key
export ssCheckVars()
begin

  ssPrint
(ssVCheckVars);
  
ssInitSSApp();
  
ssInitVars();

  
local j,n;
  
local avarlist:=AVars();
  
local varlist:=ssCurSys(4);
  
n:=size(varlist);

  for 
j from 1 to n do
    if 
NOT(pos(avarlist,varlist(j)) OR pos(ssGlobal,varlist(j))) then
      
return(0);
    
end;
  
end;

  
n:=size(avarlist);
  for 
j from 1 to n do
    if ( (
avarlist(j) <> ssVarKey) AND NOT(pos(varlist,avarlist(j))) ) then
      
return(0);
    
end;
  
end;
  return(
1);

end;


// do we have any equations
//  1: yes, equations in symb view
//  0: no equations at all
// -1: yes, but only saved in library
ssHaveEqns()
begin
  local j
;
  for 
j from 0 to 9 do
    if 
ISCHECK(jthen return(1); end;
  
end;

  if (
ssLibSize == 0then return(0); end;

  if (
type(ssCurSys) <> 6then return(0); end;

  if 
size(ssCurSysthen
    
if size(ssCurSys(2)) then
      
return(-1);
    else
      return(
0);
    
end;
  else
    return(
0);
  
end;
end;


// UI for creating new variables
ssCreateVar()
begin
  local run
:=1;
  
local n;
  
local varname:=""varinfo:="";
  
local ow:=0;

  
ssInitSSApp();
  
ssInitVars();

  while 
run do
    if 
input(
      {
        {
varname, [2], {30650}},
        {
varinfo, [2], {30651}},
        {
ow1, {30,10,2}}
      },
      
ssTNewVar,
      { 
ssLNamessLDescrssLOWrite },
      { 
ssHNamessHDescrssHOWrite }
    )
    
then

      
if size(varname)<1 then
        msgbox
(ssNullName);
      else
        
n:=pos(AVars,varname);
        if 
n then
          
if ow then
            n
:=pos(ssCurSys(4),varname);
            
ssCurSys(5,n):=varinfo;
            
run:=0;
          else
            
msgbox(ssEOW varname);
          
end;
        else
          
iferr

            
if NOT(pos(ssGlobal,varname)) then
              AVars
(varname):=0;
            
end;

          
then
            msgbox
(ssInvName);
          else
            
purge(EVAL(varname));
            
ssCurSys(4,0):=varname;
            
ssCurSys(5,0):=varinfo;
            
ssCurSys(6,0):=0;
            
ssCurSys(7,0):=0;
            
msgbox(ssVVarMade varname);
            
varname:=""varinfo:="";
          
end;
        
end;
      
end// end null name

    
else
      
run:=0;
    
end;

  
end// end while
end;


// save current equations
ssSaveEqns()
begin
  local j
,k,n1,n2;
  
local cmd:="";
  
local oldeqn:="";
  
local neweqn:="";
  
local markadd:=0;
  
local neweqns:={};
  
local teqnlist:={};
  
local tsellist:={};

  if 
ssCheckVars() then

    ssPrint
(ssVLoadEqns);
    
n1:=ssEqPage*10+1;
    if (
ssEqPage ssEqPages(1)) then
      n2
:=n1+9;
    else
      
n2:=n1+ssEqPages(2);
    
end;

    for 
j from n1 to n2 do
      
k:= j mod 10;
      
cmd:="string(E" string(k,1,0) + ",1,12)";

      
iferr
        neweqn
:=expr(cmd);
      
then
        neweqn
:="";
      else
        if 
ssNullSys then
          oldeqn
:="";
        else
          
cmd:="E" string(k,1,0) + ":=" string(ssCurSys(2,j));
          
iferr expr(cmd); then end;
          
cmd:="string(E" string(k,1,0) + ",1,12)";
          
iferr oldeqn:=expr(cmd); then end;
        
end;
        if (
oldeqn <> neweqnthen
          
if ssNullSys then
            ssCurSys
(2,0):=neweqn;
          else
            
ssCurSys(2,j):=neweqn;
          
end;
        
end;
      
end;

      
cmd:="E" string(k,1,0) + ":=" string(neweqn);
      
iferr expr(cmd); then
        
// msgbox(ssSubmitBug);
      
end;

      if 
ISCHECK(kthen
        ssCurSys
(3,j):=1;
      else
        
ssCurSys(3,j):=0;
      
end;

      if (
size(neweqn) == 0then
        ssCurSys
(3,j):=-1// mark for delete
      
end;
    
end;  // end for j

    
n2:=n1+9;
    for 
k from j to n2 do
      
n1:=k mod 10;
      
cmd:="string(E" string(n1,1,0) + ",1,12)";
      
iferr
        neweqn
:=expr(cmd);
      
then
        
// nop
      
else
        if 
size(neweqnthen
          neweqns
(0):=neweqn;
          
neweqns(0):=ISCHECK(n1);
          
markadd:=1;
        
end;
      
end;
    
end// end for k

    // rebuilt existing equations
    
k:=0;
    
n2:=size(ssCurSys(2));
    for 
j from 1 to n2 do
      if (
ssCurSys(3,j) >= 0then
        teqnlist
(0):=ssCurSys(2,j);
        
tsellist(0):=ssCurSys(3,j);
        
k:=k+1;
      
end;
    
end;
    
ssCurSys(2):=teqnlist;
    
ssCurSys(3):=tsellist;

    if 
markadd then
      n2
:=size(neweqns)/2;
      for 
j from 1 to n2 do
        
ssCurSys(2,0):=neweqns(2*j-1);
        
ssCurSys(3,0):=neweqns(2*j);
        
k:=k+1;
      
end;
    
end;

    
ssEqPages(1):=ip((k-1)/10);
    
ssEqPages(2):=(k-1mod 10;
    
ssEqPage:=min(max(0,ssEqPage),ssEqPages(1));

    if 
k then
      ssNullSys
:=0;
    else
      
ssNullSys:=1;
    
end;

    return(
1);

  else
    
msgbox(ssAbort);
    return(
0);
  
end;
end;


// set up equations in Symb view
export ssLoadSymb()
begin

  local j
,k,n1,n2;
  
local cmd:="";

  
// no equations to populate Symb view?
  
if ssNullSys then 
    
for j from 0 to 9 do
      
cmd:="E" string(j,1,0) + ":=" string("");
      
expr(cmd);
    
end;
    return(
1);
  
end;

  
ssPrint(ssVLoadEqns);
  
n1:=ssEqPage*10+1;
  if (
ssEqPage ssEqPages(1)) then
    n2
:=n1+9;
  else
    
n2:=n1+ssEqPages(2);
  
end;
  for 
j from n1 to n2 do
    
k:= j mod 10;
    
cmd:="E" string(k,1,0) + ":=" string(ssCurSys(2,j));
    
iferr expr(cmd); then end;
    if (
ssCurSys(3,j)==1then CHECK(k); else UNCHECK(k); end;
  
end;

  
n2:=n1+9;
  for 
k from j to n2 do
    
n1:=k mod 10;
    
cmd:="E" string(n1,1,0) + ":=" string("");
    
expr(cmd);
  
end;

  return(
1);

end;


// select an equations page
ssSelectEqPage()
begin
  ssInitSSApp
();
  
local j;
  
local n:=ssEqPages(1)+1;
  
local page:=ssEqPage+1;
  
local curpage:=page;
  
local pagelist:={};
  
local title:="[" string(page,1,0) + "/" string(ssEqPages(1)+1,1,0) + "] " ssTSelPage;
  
  
pagelist:=makelist(j,j,1,n);
  
pagelist(0):=ssTNewPage;

  if 
choose(page,title,pagelistthen

    
if (curpage <> pagethen
      ssSaveEqns
(); 

      if (
page == (n+1)) then

        
if (ssNullSys == 0then 
          ssEqPages
(1):=n+1;

          
// fill last page
          
if (ssEqPages(2) < 9then
            n
:=9-ssEqPages(2);
            for 
j from 1 to n do
              
ssCurSys(2,0):="";
              
ssCurSys(3,0):=-1// mark for deletion
            
end;
          
end;
        
end;

        
// create new page
        
for j from 1 to 10 do
          
ssCurSys(2,0):="";
          
ssCurSys(3,0):=-1// mark for deletion
        
end;

        
n:=size(ssCurSys(2));
        
ssEqPage:=ip((n-1)/10);
        
ssEqPages(1):=ssEqPage;
        
ssEqPages(2):=(n-1mod 10;
        
ssNullSys:=0;

      else

        
// not creating new blank page
        
ssEqPage:=min(max(0,page-1),ssEqPages(1));

      
end// if newpage or existing page

    
end// if selpage <> page

    
ssLoadSymb();

  
end// if choose
end;


// set new system
export ssSetSystem(n)
begin
  
if (ssLibSizethen
    
return(0);
  
end;

  
ssCurSysIndex:=n;
  
ssCurSys:=ssCurLib(n);
  
ssUpdateSys();
  
ssInitVars();
  
ssLoadSymb();
end;


ssErrorPage(n,msg,eqn)
begin
  local p
:=ip((n-1)/10)+1;
  
msgbox(msg ":\n" eqn);
end;


// check if equations are valid
// assumes equations have been saved
export ssCheckEqns()
begin
  local n
:=size(ssCurSys(2));
  
local eqn:="";
  
local j,k,v;
  
local varlist:={};

  if 
n then

    
// check each equation
    
for j from 1 to n do
      
eqn:=ssCurSys(2,j);

      
// do we have = symbol?
      
if instring(eqn,"="then
        iferr eqn
:=string(E0,1,12); then eqn:=""end;
        
E0:=ssCurSys(2,j);
        
varlist:=LNAME(E0);
        
v:=size(varlist);
        if 
v then
          
for k from 1 to v do
            if (
pos(ssCurSys(4),string(varlist(k))) == 0then
              ssErrorPage
(ip((j-1)/10)+1,ssNonVar,ssCurSys(2,j)+"\n> "+varlist(k));
              
iferr E0:=eqnthen end;
              return(
0);
            
end;
          
end;
        else
          
// constants only? not equation
          
ssErrorPage(j,ssNotEqn,ssCurSys(2,j));
          
iferr E0:=eqnthen end;
          return(
0);       
        
end;
        
iferr E0:=eqnthen end;
        
      else
        
// no equal symbol; report page
        
ssErrorPage(j,ssNotEqn,eqn);
        return(
0);
      
end;
    
end;

    
// all eqns seem ok
    
return(1);

  else
    
// no equations to check
    
return(-1);
  
end;
end;


// save current system
// no null names but does not check
// validity of names beyond whether
// AVars will accept such a name
ssSaveSystem()
begin
  ssSaveEqns
();

  
local sysname:=ssCurSys(1);
  
local eqns:=ssCurSys(2);
  
local vars:=ssCurSys(4);
  
local eqn,var,n;
  
local run:=1;

  
// bug in input when choose lists are empty
  
if (size(eqns) < 1then eqns:={ ssVNoEqns }; end;
  if (
size(vars) < 1then vars:={ ssVNoVars }; end;


  while 
run do
    if 
input(
      {
        { 
sysname, [2], { 1575} },
        { 
eqneqns, { 1575} },
        { var, 
vars, { 1575} }
      },
      
ssTSaveSys,
      { 
ssLName,    ssLEqnsssLVars },
      { 
ssHSysNamessHEqnsssHVars }
    )
    
then

      
if size(sysnamethen
        
// maybe later add check for dupes
        
n:=pos(ssSysTitlessysname);

        if 
ssCheckEqns() then
          ssCurSys
(1):=sysname;
          
ssCurLib(ssCurSysIndex):=ssCurSys;
          
AFiles(ssLibFN):=ssCurLib;
          if (
ssCurSysIndex == 0then ssCurSysIndex:=size(ssCurLib); end;
          
ssLibSize:=size(ssCurLib);
        else
          
ssWarn(ssNotSaved);
        
end;
        
run:=0;

      else
        
msgbox(ssNullName);
      
end;

    else
      
// user canceled
      
ssWarn(ssNotSaved);
      
run:=0;
    
end;

  
end// end while;
end;

// create a system
ssNewSystem()
begin
  ssCurSys
:={ssTNewSys, {}, {}, {}, {}, {}, {} };
  
ssCurSysIndex:=0;
  
ssUpdateSys();
  
ssInitVars();
  
ssLoadSymb();
  
startview(0,1);
end;


ssChooseSys()
begin
  local n
,t;
  
local run:=1;
  
local systitles:={};

  
n:=ssCurSysIndex;

  
iferr
    ssCurLib
:=AFiles(ssLibFN);
  
then
    ssWarn
(ssNoLibDat);
    
ssCurLib:={};
    
AFiles(ssLibFN):=ssCurLib;
  
end;
  
ssLibSize:=size(ssCurLib);

  if 
ssLibSize then
    systitles
:=makelist(ssCurLib(n,1),n,1,ssLibSize);
  else
    
systitles:={};
  
end;
  
ssSysTitles:=systitles;
  
systitles(0):=ssTNewSys;

  
t:=choose(nssTChooseSyssystitles);
  if 
t then
    
if ( <= ssLibSize then
      ssSetSystem
(n);
    else
      
ssNewSystem();
    
end;
    return(
1);
  
end;
  return(
0);
end;


// UI for deleting systems
export ssDeleteSys()
begin
  local cmd
:="input({";
  
local systitles;
  
local j;
  
local selected:={};
  
local lib:={};

  if 
ssLibSize then
    selected
:=makelist(0,j,1,ssLibSize);
    
systitles:=makelist(ssCurLib(j,1),j,1,ssLibSize);
    for 
j from 1 to ssLibSize do
      
cmd:=cmd "{selected(" string(j,1,0) + "),0,{94,5," string(j-1,1,0) + "}}";
      if (
j<ssLibSizethen cmd:=cmd ",\n"end;
    
end;
    
cmd:=cmd "},\n" string(ssTDeleteSys) + ",\n{";
    for 
j from 1 to ssLibSize do
      
cmd:=cmd string(ssCurLib(j,1));
      if (
j<ssLibSizethen cmd:=cmd ",\n"end;
    
end;
    
cmd:=cmd "},\n{";
    for 
j from 1 to ssLibSize do
      
cmd:=cmd string(ssHMarkDel);
      if (
j<ssLibSizethen cmd:=cmd ",\n"end;
    
end;
    
cmd:=cmd "},\n" string(selected,1,0) + ",\n" string(selected,1,0) + ")";
    
Notes("eqlib_debug.log"):=cmd;
    
j:=expr(cmd);

    if 
j then

      
// current system deleted? if so set index to 0
      
if ssCurSysIndex then
        
if selected(ssCurSysIndexthen
          ssCurSysIndex
:=0;
        
end;
      
end;

      
// rebuild library and adjust index
      
for j from 1 to ssLibSize do
        if 
NOT(selected(j)) then
          lib
(0):=ssCurLib(j);
          if (
ssCurSysIndexthen
            ssCurSysIndex
:= ssCurSysIndex 1;
          
end;
        
end;
      
end;
      
ssCurLib:=lib;
      
AFiles(ssLibFN):=ssCurLib;

    
end;

  else
    
ssWarn(ssNoSystems);
  
end;
end;


// variable browser
export ssVarBrowser()
begin
  local vals
:=ssCurSys(6);
  
local cons:=ssCurSys(7);
  
local cmd:="input({";
  
local n:=size(vals);
  
local j,k;
  
local tmp:="";
  
local xloc:="15,75";

  if (
n<1then
    msgbox
(ssNoVars);
    return(
0);
  
end;

  
k:=1;
  for 
j from 1 to n do
    
k:=max(k,size(ssCurSys(4,j)));
  
end;

  if (
3then xloc:="30,60"end;

  
// build input( ... )

  // { variable, type, { pos } }
  
for j from 1 to n do
    
k:=pos(ssGlobalssCurSys(4,j));
    if (
k<28then tmp:="0"; else tmp:="0,3"end;
    
    
cmd:=cmd "{vals(" string(j,1,0) + "),[" tmp "],{" xloc "," string(j-1,1,0) + "}}, ";
    
cmd:=cmd "{cons(" string(j,1,0) + "),0,{94,5," string(j-1,1,0) + "}}";
    if ((
n>1) AND (j<n)) then cmd:=cmd ",\n"end;
  
end;

  
// add title
  
cmd:=cmd "},\n" string(ssCurSys(1) + " Variables") + ",\n{";

  
// add labels
  
for j from 1 to n do
    
cmd:=cmd string(ssCurSys(4,j) + "=") + ", " string("");
    if ((
n>1) AND (j<n)) then cmd:=cmd ",\n"end;
  
end;
  
cmd:=cmd "},\n{";

  
// add help
  
for j from 1 to n do
    
cmd:=cmd string(ssCurSys(4,j) + ": " ssCurSys(5,j)) + "," string(ssHMakeConst);
    if ((
n>1) AND (j<n)) then cmd:=cmd ",\n"end;
  
end;
  
cmd:=cmd "},\n";

  
// add init and reset vals
  
tmp:="{";
  for 
j from 1 to n do
    
tmp:=tmp vals(j) + "," cons(j);
    if ((
n>1) AND (j<n)) then tmp:=tmp ","end;
  
end;
  
tmp:=tmp "}";
  
cmd:=cmd tmp ",\n" tmp ")";

  
Notes("eqlib_debug.log"):=cmd;
  
j:=expr(cmd);

  if 
j then
    ssCurSys
(6):=vals;
    
ssCurSys(7):=cons;

    for 
j from 1 to n do
      if 
pos(ssGlobal,ssCurSys(4,j)) then
        expr
(ssCurSys(4,j) + ":=" vals(j));
      else
        
AVars(ssCurSys(4,j)):=vals(j);
      
end;
    
end;
  
end;

  return(
j);

end;


// build F, F(var1, var2, ...) and Jacobian
// assumes all equations and variables have been
// validated; also assumes equations are saved and
// that selectd equations form a non-null list
// saves F as ssF (CAS variable)
export casMakeF()
begin
  local cmd
:="['";
  
local cmd2:="[";
  
local j,n;
  
local varlist:={};
  
local eqnlist:={};
  
local k:=size(ssCurSys(4));
  
local vstr1:="";
  
local vstr2:="";
  
local vstr3:="";

  
n:=size(ssCurSys(2));
  for 
j from 1 to n do
    if 
ssCurSys(3,jthen
      eqnlist
(0):=ssCurSys(2,j);
    
end;
  
end;

  for 
j from 1 to k do
    if 
NOT(ssCurSys(7,j)) then
      varlist
(0):=j;
    
end;
  
end;
  
ssSolveVars:=varlist;

  
n:=k-1;
  for 
j from 1 to n do
    
vstr1:=vstr1 ssCurSys(4,j) + ",";
  
end;
  
vstr1:=vstr1 ssCurSys(4,k);

  
n:=size(varlist)-1;
  for 
j from 1 to n do
    
vstr2:=vstr2 ssCurSys(4,varlist(j)) + ",";
  
end;
  
vstr2:=vstr2 ssCurSys(4,varlist(n+1));

  
// ssF:=( vars ) -> [ f1, f2, ... ]
  
n:=size(eqnlist)-1;
  for 
j from 1 to n do
    
cmd:=cmd eqnlist(j) + ")','";
    
cmd2:=cmd2 eqnlist(j) + "),";
  
end;
  
cmd:=cmd eqnlist(n+1) + ")']";
  
cmd:=replace(cmd,"=","-(");
  
CAS(EVAL("ssF:=" cmd));
  
cmd2:=cmd2 eqnlist(n+1) + ")]";
  
cmd2:=replace(cmd2,"=","-(");
  
CAS(EVAL("ssFx:=(" vstr1 ")->(" cmd2 ")"));

  
cmd:="ssJ:=transpose(diff(" cmd ",[" vstr2 "]))";
  
CAS(EVAL(cmd));
end;


// Newton's Method
// dx = - J^(-1) * F
// x[n+1] = x[n] + dx
export casNewton()
begin
  local j
,k,nsv,nv;
  
local dx;
  
local var;
  
local tolF:=1.0E-8// exit if F.F < tolF
  
local nsF=2*tolF// initial squared norm of F
  
local vecNewt:={};
  
L1:={};

  
nv:=size(ssCurSys(4));
  
nsv:=size(ssSolveVars);
  for 
j from 1 to nv do
    
vecNewt(0):=ssCurSys(6,j);
  
end;
  
  for 
k from 1 to 100 do
    
nsF:=CAS("approx(ssF*ssF)");
    if (
nsF tolFthen break; end;
    
dx:=CAS("-ssJ^(-1)*transpose(approx(ssF))");
    for 
j from 1 to nsv do
      var:=
ssCurSys(4,ssSolveVars(j));
      if 
pos(ssGlobal,var) then
        expr
(var + ":=" + var + "+" dx(j,1));
      else
        
AVars(var):=AVars(var) + dx(j,1);
      
end;
      
ssCurSys(6,ssSolveVars(j)):=expr(var);
    
end// for j

    
for j from 1 to nv do
      
vecNewt(0):=ssCurSys(6,j);
    
end;
  
end// for k

  
return(list2mat(vecNewt,nv));

end;


START()
begin
//  startview(-1,1);
  
ssInitSSApp();
  
ssInitVars();
  
startview(0,1);
end;


// Equations Editor
Symb()
begin
  
if ssInit then
    ssSaveEqns
();
  else
    
ssInitSSApp();
    
ssInitVars();
  
end;
  
ssLoadSymb();
  
startview(0,1);
end;


// System of Equations browswer
Plot()
begin
  
if ssInit then
    ssSaveSystem
();    
  else
    
ssInitSSApp();
    
ssInitVars();
  
end;
  
ssChooseSys();
  
startview(0,1);
end;


// run solver
Num()
begin
  local matNewt
:=[[0]];
  
local j;
  
local tlist:={};
  
local labels:={};
  if 
ssInit then
    ssSaveEqns
();
    
ssVarBrowser();
    
casMakeF();
    
matNewt:=casNewton();
    
tlist(0):=ssCurSys(1);
    
tlist(0):={};
    for 
j from 1 to size(ssSolveVars) do
      
labels(0):=ssCurSys(4,ssSolveVars(j));
    
end;
    
tlist(0):=labels;
    
editmat(matNewt,tlist);
  else
    
ssInitSSApp();
    
ssInitVars();
  
end;
end;


// Set up initial guess 
NumSetup()
begin
  
if ssInit then ssSaveEqns(); end;
  
ssVarBrowser();
end;


// select equations page (View Menu)
view "Select Page"ssMenuEqnPage()
begin
  ssSelectEqPage
();
  
startview(0,1);
end;


// UI for creating new variables (View Menu)
view "Add/Edit Variable"ssMenuNewVar()
begin
  ssCreateVar
();
end

// reload saved equations (View Menu)
view "Restore Equations"ssMenuLoadEqns()
begin
  
if ssCurSysIndex then
    ssCurSys
:=ssCurLib(ssCurSysIndex);
    
ssUpdateSys();
    
ssInitVars();
  
end;
  
ssLoadSymb();
  
startview(0,1);
end;


// save current system (View Menu)
view "Save System"ssMenuSaveSys()
begin
  ssSaveSystem
();
end;

// create new system (View Menu)
view "New System"ssMenuNewSys()
begin
  ssSaveSystem
();
  
ssNewSystem();
end;

// delete existing system (View Menu)
view "Delete System"ssMenuDelSys()
begin
  ssSaveSystem
();
  
ssDeleteSys();
end;

// select system (View Menu)
view "Select System"ssMenuSetSys()
begin
  ssSaveSystem
();
  if 
ssChooseSys() then startview(0,1); end;
end

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
01-31-2017, 01:35 PM
Post: #51
RE: Creating an equation library (updated)
Thnks for version 0.05, but I still get a restart on my phisical unit when I press [Num], [Plot] or [View] and then option "Add or edit variable"
However, on my virtual calculator it works well. Could be there is some old files from the earlier version on my phisical calculator that corrupts the system?
And is there an option for solving system of equations "on the go" using your engine, for just inserting the equations without defining the variables previously?. The variables will be created automatically in the solver menu ([Num]).
Find all posts by this user
Quote this message in a reply
01-31-2017, 02:55 PM (This post was last modified: 01-31-2017 04:53 PM by Han.)
Post: #52
RE: Creating an equation library (updated)
(01-31-2017 01:35 PM)akmon Wrote:  Thnks for version 0.05, but I still get a restart on my phisical unit when I press [Num], [Plot] or [View] and then option "Add or edit variable"
However, on my virtual calculator it works well. Could be there is some old files from the earlier version on my phisical calculator that corrupts the system?

I have only been using the program on the virtual calc and so far have not had any crashes other than the empty choose list I described earlier. Are you pressing [Num] prior to inputting any variables and equations? It may be you are still running into empty list issues if so. The solver right now makes little to no checks whether there is a valid system; you will need to ensure that it does. The last thing to check is if your "Equation Library.lib" app file is not corrupt. Back it up, and simply delete it.

EDIT: So I just tried to run it on the actual calculator and am seeing some warmstarts (calculator resets). I managed to trace it down to the return() statement in the ssInitVars() program. It looks like either you and I have both the same memory corruption, or there is indeed a bug the current firmware with respect to return() within an app.

Quote:And is there an option for solving system of equations "on the go" using your engine, for just inserting the equations without defining the variables previously?. The variables will be created automatically in the solver menu ([Num]).

No, and that is due to a limitation of how variables are created on the calculator. (In order to use the built-in equation editor in the Symb view, only existing variables are allowed.) One can only hope that in the future they will modify app behaviors so that entering formulas in the symbolic view, app variables are automatically created. I am not sure why that has not been made to be the default behavior. At the moment, I prefer not to have to build a custom equation editor.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
02-01-2017, 12:36 AM
Post: #53
RE: Creating an equation library (updated)
(01-31-2017 01:35 PM)akmon Wrote:  And is there an option for solving system of equations "on the go" using your engine, for just inserting the equations without defining the variables previously?. The variables will be created automatically in the solver menu ([Num]).

So I thought about this a bit more and there are some alternatives we can consider. Using only global variables (A-Z,theta,Z0-Z9) could work for "on-the-fly" use. I believe I can properly parse all relevant variables so that users never have to specify them as being part of the the variables list provided that these variables are restricted to global types. Again, the limitation is mainly in the command line in the Symb view. It does not allow you to type expressions using non-existent variables (so globals work, but something like 'myvar' will not unless it already exists in the system).

For the moment, this is not too high on my priority list. I would rather focus on the convergence of Newton's method, and the error handling for different systems (ill-conditioned, over/under determined, etc.) If enough people would like an on-the-fly setup, then perhaps we can then bump it up to higher priority.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
02-01-2017, 11:24 AM
Post: #54
RE: Creating an equation library (updated)
I agree that the firs step is working on the engine of solving the system, that´s true.

In my hopes, I admit I´m nostalgic with the old Solvesys library from Hp48, 49, I inserted several equations, and the program "ate" them solving the variables amazingly, with no need to create them. So now you know which are my priorities. Of the course, managing files of equations i awesome and useful, but it´s easier to program. The main engine is the most important part of the proyect, my point of view is have both worlds for using from a way or other: the file manager stores all equations, clasified with menus, choose boxes etc. But once the equations are selected, launch the engine to solve them, or if you don´t want to use the file manager, and just only press the engine and solve some equations "on-the-fly" it could be done. The problem is the automatic creation of variables, it´s strange there is no command that extracts them from the equation.
Find all posts by this user
Quote this message in a reply
02-01-2017, 12:35 PM (This post was last modified: 02-01-2017 12:36 PM by Han.)
Post: #55
RE: Creating an equation library (updated)
(02-01-2017 11:24 AM)akmon Wrote:  I agree that the firs step is working on the engine of solving the system, that´s true.

In my hopes, I admit I´m nostalgic with the old Solvesys library from Hp48, 49, I inserted several equations, and the program "ate" them solving the variables amazingly, with no need to create them. So now you know which are my priorities. Of the course, managing files of equations i awesome and useful, but it´s easier to program. The main engine is the most important part of the proyect, my point of view is have both worlds for using from a way or other: the file manager stores all equations, clasified with menus, choose boxes etc. But once the equations are selected, launch the engine to solve them, or if you don´t want to use the file manager, and just only press the engine and solve some equations "on-the-fly" it could be done. The problem is the automatic creation of variables, it´s strange there is no command that extracts them from the equation.

Once the equations have been created, then extracting variables can be done using LNAME. However, one cannot enter equations into the Symb view using variables that do not already exist (i.e. entering equations that involve only global variables like A-Z is ok, but using a custom variable name that has never been created will result in an syntax error when using the Symb view). That is just a quirk with the HP Prime's non-CAS side -- you cannot enter formulas that use variables that do not exist. Using the Symb view means not having to create a brand new interface for entering functions (plus, it gives you pretty-print AND it has some basic form of syntax checking). And the Symb view's behavior is the only reason users have to first "create" non-global variables. In the end, I went ahead and enforced this rule for all variables for consistency. Another motivating factor was that for an equation library, the variables should really have some sort of description, which could be added during the variable editing/addition step.

I too loved how you could just make a symbolic expression on the HP48-HP50 series and never have to "declare" variables. From time to time, it still bugs me that it is not always the case on the HP Prime.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
02-01-2017, 03:24 PM (This post was last modified: 02-01-2017 03:36 PM by Han.)
Post: #56
RE: Creating an equation library (updated)
Here's a version that _should_ enable automatically manage pre-existing variables so that you do not have to manually add them to the system. If they already exist, then they will be included into the system definition on the fly (with an empty description that can be changed using the add/edit variable menu item in [View]).

Source here: http://www.hpmuseum.org/forum/thread-2824.html

You will need to manually set the flag ssAutoVar to 1 using:

ssAutoVar:=1;

In the future, this will probably default to 0 (because users need to understand that the HP Prime simply will not auto-create user variables). The intent is that this setting and can be changed via a settings page (does not exist yet; have not coded it).

The code is posted in the very first post. I'll be updating only the first post from here on out so that:

1) we don't keep bumping this thread unnecessarily
2) it doesn't grow in size with newer versions (i.e. only the code in the first post will change as updates occur)

Once it is in a release state, I'll move it into the software library forum.

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
02-02-2017, 11:46 PM
Post: #57
RE: Creating an equation library (Updated 1-FEB-2017)
So it looks like we've hit another snag. The SVD technique for pseudo inverses handles literally all possible cases of systems (over determined, under determined, ill conditioned, etc). The problem is that the SVD as implemented on the calculator is incomplete (it does not handle matrices with 0 as a singular value). I tried to use my own SVD program, but it would appear that it too has issues -- issues which I cannot trace as of yet. It also doesn't help that the exact same code on the HP returns something different from xcas Undecided

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
03-05-2017, 09:50 PM
Post: #58
RE: Creating an equation library (Updated 03-FEB-2017)
I thought this thread needed a proper conclusion. For those who do not already know, this project now exists as an actual app: http://www.hpmuseum.org/forum/thread-7725.html

All issues with the SVD program are now resolved (to the best of my knowledge).

As a side note, the reference manual has been updated. (I am particularly fond of page 41 in the reference manual; see link above for more info)

Graph 3D | QPI | SolveSys
Find all posts by this user
Quote this message in a reply
03-06-2017, 11:55 AM
Post: #59
RE: Creating an equation library (Updated 03-FEB-2017)
I have been following this thread with interest but I won't actually need such a program. I do need your SVD program separate from the Solvesys program, though. Is that available in the latest version?
Thanks!
Find all posts by this user
Quote this message in a reply
03-06-2017, 12:04 PM
Post: #60
RE: Creating an equation library (Updated 03-FEB-2017)
Never mind! I just found it. Thanks for your contribution!
Find all posts by this user
Quote this message in a reply
Post Reply 




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