cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
The Discovery Summit 2025 Call for Content is open! Submit an abstract today to present at our premier analytics conference.
See how to use to use Text Explorer to glean valuable information from text data at April 25 webinar.
Choose Language Hide Translation Bar
View Original Published Thread

Setting up a recursive loop in jsl

Sburel
Level IV

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