cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
  • Sign-in to the JMP Community will be unavailable intermittently Dec. 6-7 due to a system update. Thank you for your understanding!
  • We’re retiring the File Exchange at the end of this year. The JMP Marketplace is now your destination for add-ins and extensions.
  • JMP 19 is here! Learn more about the new features.

Discussions

Solve problems, and share tips and tricks with other JMP users.
Choose Language Hide Translation Bar
Sburel
Level IV

Setting up a recursive loop in jsl

hi,

 

I've built a long script where a curve fitting is performed iteratively on a large data table which many variables listed in 1 column. However at the end of the process some of those variables are not fitted (the process failed for one reason or another). At this point, I create a 'failed fitting' list of the variables that were not fitted in the previous and create a subset from the source table  (select where/contains/subset) and run part of the initial script again (that portion of the script is wrapped in an expression) on the subset table (selected rows, all columns) .

At the end of the second round of fitting, a new  'failed fitting ' list is created (typically smaller). 

I'm trying to find a way to create a recursive loop where the code would look for the size of the last  'failed fitting' list and if it is greater than 0 and different from the previous 'failed fitting' list, it will initiate another round of fitting until the 'failed fitting'=0 or is identical to the previous 'failed fitting' list ( to avoid creating an infinite loop).

 

Any suggestions would be greatly appreciated.

 

Sebastien

5 REPLIES 5
jthi
Super User

Re: Setting up a recursive loop in jsl

JMP does provide recursion with Recurse(). I think you can also recall the same function again to make it recursive

Using recurse():

Names Default To Here(1);
ex rev = Function({s},
	If(Length(s) <= 1,
		s,
		Recurse(Substr(s, 2)) || Left(s, 1)
	)
);
ex rev("abcd");

Calling same function:

Names Default To Here(1);
ex rev = Function({s},
	If(Length(s) <= 1,
		s,
		ex rev(Substr(s, 2)) || Left(s, 1)
	)
);
ex rev("abcd");
-Jarmo
Sburel
Level IV

Re: Setting up a recursive loop in jsl

Hi @jthi,

 

thanks for the tip. I'll give it a shot

 

Sebastien

Sburel
Level IV

Re: Setting up a recursive loop in jsl

Hi @jthi,

 

Thanks for your original input. Unfortunately, I have not managed to turn your suggestion into a workable script.

 

So I'm attaching another description of my objective (not a function script but rather a 'workflow').

 

Hopefully, someone can point me in the right direction. 

 

Thanks

 

Sebastien

names default to here(1);
clear log();


sourcefitting={"a","b","c","d","e","f"};
/*The sourcefitting list can be 1000s longs and split in batches to perform some curve fitting, parameter extraction and them summarization using a FOR loo into a master table. 
The process is expected to fail on some of those batches. 
The failed items are identifed/listed into the 'failedfitting" list. 
At which point a recursive loop using 'processX' needs to be implemented to take care of the remaining items using a new round of batching and fitting (for some reason the 'failing' process works on smaller batches but predicting which one will failed is not possible hence the need for a recessive loop), until the 'failedfittingX' list' is either empty or is stagnating (processfitting=1) ie the process keeps on failing and running the process another round is not longer warranted.
 */


processX=expr(/* process XYZ*/ //each time the processX is run 2 list are generated "succesfittingX" and "failedfittingX" are generated

//A new list "successfittingX" is generated at the end of the recursive loop
successfitting0={"a","c","d"};
/*
successfitting1={"a","c","d","b"};
successfitting2={"a","c","d","b","e"};
successfitting3={"a","c","d","b","e","f"}*/;// or successfitting3={"a","c","d","b","e"};
successfitting=successfittingX;

//The successfittingX and the sourcefitting lists are compared and a resulting list "failedfittingX" is created:

failedfitting0={"b","e","f"};
/*
failedfitting1={"e","f"};
failedfitting2={"f"};
failedfitting3={}*/; // or failedfitting3={"f"};
failedfitting=failedfittingX;
failednb=Nitems(failedfitting);
if(failedfittingX==failedfittingX-1,progressfitting=1, progressfitting=0);
);



//The issue is about correctly defining the structure recursive loop which uses the previous list to determine wheter the process needs to keep on going or if it is completed
// the use of the function 'recurse' has been suggested

testrec=function({failednb},
		if(failednb>0&processfitting=0 ,recurse( processX),show("Done"))
);
testrec(failednb);

 

Craige_Hales
Super User

Re: Setting up a recursive loop in jsl

I would not use recursion for this. Use a list of WorkToBeDone and a list of WorkCompleted and a flag FoundSomething. Write your loop something like this:

 

good = function({ method, item), 
// use the current strategy/method to test the item
// return 1 if pass, 0 if fail
);

FoundSomething = 1; // flag: are we still making progress?
strategy = 1; // maybe change the strategy after each round
while(FoundSomething,
    FoundSomething = 0;
    for(i = nitems(WorkToBeDone), i>=1, i -= 1, // backwards because removing items
        if( good( strategy, WorkToBeDone[i] ),
            insertinto(WorkCompleted, removefrom(WorkToBeDone,i));
            FoundSomething = 1;
        )
    );
    strategy += 1; // new strategy for next round
);
Craige
Sburel
Level IV

Re: Setting up a recursive loop in jsl

@Craige_Hales Thanks a lot for the suggestion. I will try this strategy.

 

Sebastien

Recommended Articles