Message Boards Message Boards

0
|
2639 Views
|
14 Replies
|
2 Total Likes
View groups...
Share
Share this post:

Matching problem with long list of list?

Posted 1 year ago

I have a function f[zs] and a function fb[zs, base] with a parameter zs that is a list of nonempty lists of integers. The parameter is defined as zs:{{__Integer}...}

For short lists the functions can be called without problem.

When the list gets longer (e.g. about 5000 elements) the parameter match of fb[zs, base] no longer works. I get an error: "General::maxrec: Recursion limit exceeded; positive match might be missed.". f[zs] still works.

f[zs] seems to remain working for even very long lists.

Can anybody explain this behavior? Is this a bug within Wolfram or is there a mistake within my coding?

Block[{digits = 8, maxAnz = 5000, f, fb, zs},
 f[zs : {{__Integer} ...}] := {Length[zs]};
 fb[zs : {{__Integer} ...}, base_Integer : 10] := {base, Length[zs]};
 Echo[$RecursionLimit, ".$RecursionLimit: "];
 (* Make zs = List of Lists *)
 zs = Partition[Range[maxAnz*digits], digits];
 Echo[Column[{{digits, Length[zs]}, Short[zs, 7]}], 
  ".{digits,Length[zs]},zs}: "];
 (* Test zs-Pattern within f[zs] *)
 Echo[Short[f[zs], 7], ".f[zs]: "];
 (* Test zs-Pattern within fb[zs,base] *)
 Echo[Short[fb[zs, digits], 7], ".fb[zs,digits]: "];
 (* The List of List - Pattern is ok *)
 Echo[zs = Take[zs, 5], ".zs begin:"];
 Trace[MatchQ[zs, {{__Integer} ...}]]
 ]
POSTED BY: Werner Geiger
14 Replies
Posted 1 year ago

Thanks!

POSTED BY: Eric Rimbey

It's intentional behavior. Pattern matching in some cases uses recursion. There is a brake in place to avoid kernel crashes from subroutine stack exhaustion. A brief history can be found here.

POSTED BY: Daniel Lichtblau
Posted 1 year ago

I'm curious to know more, but that link doesn't look right to me. Or it's not obvious where the relevant discussion starts. Can you check it or give some explanation?

POSTED BY: Eric Rimbey

I'll track it down later. Morning coffee and a ten year old iPad...

I should be glad this bit of hardware isn't a defiant teenager.

Later edit: I think the link should work now. No idea how that previous one got copied to clipboard. The iPad keeps its secrets.

POSTED BY: Daniel Lichtblau
Posted 1 year ago

Thanks! The link does work now. There's not much there about the root cause. I see something about backtracking, which is intriguing. I guess what flummoxed me is that it seems to only happen when one argument is given a default value, which doesn't intuitively (to me) seem like it should matter all that much. It seems like the argument patterns aren't independent--somehow it's the full argument-list-pattern that's being evaluated at once, maybe?

Anyway, it's not important, but if you had time to describe the implementation details enough to explain this behavior, I'd find it interesting. Or point to a reference with more details.

POSTED BY: Eric Rimbey

Eric,

I do not remember those details at all well. Indeed, I have to remind myself how things work any and every time I need to work with pattern matching code (I suppose that holds for pretty much all code I look at).

The rough idea is this. Certain pattern types, such as Blank(Null)Sequence and Repeated(Null), can match things of varying length. These tend to be "hard" cases, and will go into code that relies on recursion to try different possible partial matches. When these patterns are nested this can go into deep recursion.

Some other pattern types can similarly cause trouble. One is Alternatives, since the different possibilities can have vary different partial match features. So again there can be deep recursion.

I realize this is on the vague side of nebulous. It's not that I do not care to share more detail, so much as I do not want to drag myself back into that code. At least not until the next (mis-)assigned bug report takes me there.

POSTED BY: Daniel Lichtblau
Posted 1 year ago

Hi Daniel, I can't say that for me your explanations and the link explained much. What is surprising is that there is interaction between parameter patterns at all. And even between a parameter and the default of another parameter. You would think that the first thing to do is isolate the individual parameters in the function definition and call, and only then would the pattern matching begin.

I'm curious to see what Wolfram Support will answer me.

POSTED BY: Werner Geiger
Posted 1 year ago

From my Email conversation with Wolfram Support I learned now that your posts here where the official Wolfram development statements concerning my CASE:4955075.

Well, if so, I miss one statement: Considers Wolfram this behavior as a bug being repaired sometimes? Or do we have to live with it?

Thanks Daniel

POSTED BY: Werner Geiger

It's a limitation. Improving on it (by removing the need for recursion) is something I do not know how to do. Hard to say if another developer will find a way in future.

In older versions the example might work. But at 10000 instead of 5000 it would crash the kernel on pretty much any operating system.

POSTED BY: Daniel Lichtblau
Posted 1 year ago

OK, Daniel. I can live with it. It needs just omitting the default for the other parameters.

POSTED BY: Werner Geiger
Posted 1 year ago

Wolfram Support has reproduced and accepted the issue and passed it to the developers.

POSTED BY: Updating Name
Posted 1 year ago

I reported the issue to Wolfram Support.

POSTED BY: Werner Geiger
Posted 1 year ago

Thanks, Eric, for your hints and work.

Since my list of lists is rectangular indeed I will use your MatrixQ condition in the form:

f[zs_ /; MatrixQ[zs, IntegerQ]] := {Length[zs]};
fb[zs_ /; MatrixQ[zs, IntegerQ], base_Integer : 10] := {base, Length[zs]};

I will lose only the condition that list entries shall be nonempty list. Which doesn't matter.

For the original problem: Like you I am now pretty convinced that this kind of interaction between a parameter pattern and the default of another parameter is just a bug within Wolfram Language.

POSTED BY: Werner Geiger
Posted 1 year ago

Weird. No answers, but some observations:

(1) This form works, but assumes that your matrix is rectangular:

fb[stuff_, base_Integer : 10] := {base, Length@stuff} /; MatrixQ[stuff, IntegerQ]

You didn't explicitly say that it should be rectangular, but your example is. I assume you can replace the condition with a more accurate one for your context. This also "works" without the condition, but then you're losing your constraints on the first argument.

(2) This also "works", but doesn't use your default:

fb[stuff : {{__Integer} ..}, base_Integer] := {base, Length@stuff}

So, it seems very much related to the default value.

(3) It doesn't help to use Default explicitly:

Default[fb] = 10;
fb[stuff : {{___} ...}, base_.] := {base, Length@stuff}

It works for small arguments, and breaks at 4999.

(4) Default values work without the extra pattern stuff:

Default[fb, 1] = {};
Default[fb, 2] = 10;
fb[stuff_., base_.] := {base, Length@stuff}

But again, you lose your other constraints.

(*) My conclusion is that this seems like a bug. But it's fascinating that there is some interaction across the argument patterns. It's also interesting that it breaks at 4999. I don't see how that's related to the recursion limit.

POSTED BY: Eric Rimbey
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract