[Jprogramming] Greatest Increasing Subsequence
Erling Hellenäs
erling at erlinghellenas.se
Thu Sep 15 08:28:53 UTC 2016
The Knuth reference can be downloaded here:
http://www.mediafire.com/download/3btahsyzax4w7xp/Vol%2C3+SortingAndSearching-Donald+Knuth.pdf
Youngs tableau is on page 47.
/Erling
On 2016-09-14 23:27, 'Mike Day' via Programming wrote:
> I suspect it's pretty near optimal. The wikipedia article points at
> Fredman's paper:
> http://www.sciencedirect.com/science/article/pii/0012365X7590103X
> analysing an algorithm of Knuth's. He shows that it performs better than
> n log2(n) - n log2 log2 (n) + O(n)
> rather than the O(n logn) cited for the function we've been looking at.
>
> I might have a play at tacit for the algorithm already discussed.
>
> Mike
>
> On 14/09/2016 14:57, Erling Hellenäs wrote:
>> Any ideas about how you could make a substantially faster tacit
>> solution to this problem or how you could make this solution
>> substantially faster? /Erling
>>
>>
>> On 2016-09-13 18:17, Erling Hellenäs wrote:
>>> Hi all !
>>>
>>> My first idea only took me down to 1 second for 10 000 numbers, 25
>>> times longer than longscseq. I then made a tacit version of
>>> longascseq. It still takes about 4 times longer than longascseq.
>>>
>>> See these two versions below.
>>>
>>> I included the full project of the tacit version.
>>>
>>> Cheers,
>>>
>>> Erling
>>>
>>> NB. Find the longest stricty increasing subsequence
>>>
>>> NB. Values are the lowest last values yet found for each subsequence
>>> length.
>>>
>>> NB. Indices are the indices of these values in the original sequence.
>>>
>>> NB. Predecessors are indices to the end of the next lower subsequence
>>>
>>> NB. for each value in the original sequence.
>>>
>>> NB. The longest sequence is found by index lookup in predecessors
>>> from the index
>>>
>>> NB. of the highest found value.
>>>
>>>
>>> Amend=:([:>[:{.[)`([:>[:{:[)`] }
>>>
>>> PickPower=: {~^:([`([:>[:{.])`([:>[:{:]))
>>>
>>> ValuesIndicesPredecessorsIndexInitialState=: [: < a:"_ , a:"_ , (([:
>>> # ]) $2:) ;0:
>>>
>>> PackValues=: <@+
>>>
>>> Values=: [: > 0 { ]
>>>
>>> Indices=: [: > 1 { ]
>>>
>>> Predecessors=: [: > 2 { ]
>>>
>>> Index=: [: > 3 { ]
>>>
>>> AdjustLength=: ((1 + [) >. [: # ]) {. ]
>>>
>>> AmendValues=: (([: {. [) ; [: {: [) Amend ([: {: [) AdjustLength Values
>>>
>>> AmendIndices=: (Index ; [: {: [) Amend ([: {: [) AdjustLength Indices
>>>
>>> AmendPredecessors=: ((([: <: [: {: [){Indices);Index ) Amend
>>> Predecessors
>>>
>>> DoBetweenElementsInFold=: ([,(Values I. [ )) ( [
>>> (Values;Indices;AmendPredecessors;1+Index)
>>> AmendValues;AmendIndices;Predecessors;Index) ]
>>>
>>> Reconstruct=: [: (Predecessors PickPower ([: i. [: - [: #
>>> Indices);[: {: Indices) [: > ]
>>>
>>> LongestIncreasingSubsequenceIndices=: [: Reconstruct [:
>>> DoBetweenElementsInFold&.:>/ ([: |. PackValues) ,
>>> ValuesIndicesPredecessorsIndexInitialState
>>>
>>> LongestIncreasingSubsequence=: ([:
>>> LongestIncreasingSubsequenceIndices ]){ ]
>>>
>>> LongestIncreasingSubsequence=: LongestIncreasingSubsequence f.
>>>
>>> NB. This is a solution to the problem of finding the longest
>>> strictly increasing subsequence.
>>>
>>> NB. Draws numbers from the end of the sequence. Selects groups with
>>> its first element larger
>>>
>>> NB. than the drawn element. Selects one of the longest of these
>>> groups if one exists and prepends
>>>
>>> NB. the drawn number. If no such group exists create a new group
>>> containing the drawn number.
>>>
>>> NB. Removes groups which are both shorter than the new group or of
>>> equal length and which starts
>>>
>>> NB. with a number which is smaller or equal to the number which
>>> starts the new group.
>>>
>>> NB. Append the new group to the remaining groups.
>>>
>>> NB. When all numbers are drawn one of the longest remaining groups
>>> is selected.
>>>
>>>
>>> GroupOfEmptyGroupInitialState=: [: < a:"_
>>>
>>> PackElements=: <@+
>>>
>>> StartsWithLonger=: ([: {.@> [) < [: {.@> ]
>>>
>>> Longer=:([: #@> [) < [: #@> ]
>>>
>>> SelectLongerOrStartsWithLonger=: (Longer +. StartsWithLonger ) # ]
>>>
>>> SelectGroupsWithLeftLessThanFirstElement=: ([ < [: {.@> ]) # ]
>>>
>>> SelectFirstGroupOfMaxLength=: ((1 <. [: # ]) {. [: I. [: (] = [: >./
>>> ]) #@>) { ]
>>>
>>> PrependLeftInGroups=: ([: < [) ,&.> ]
>>>
>>> AddGroupWithLeftIfNoGroups=: ((0 = [: # ]) {. [: < [) , ]
>>>
>>> DoBetweenElementsInFold=: ([: {. [ AddGroupWithLeftIfNoGroups [
>>> PrependLeftInGroups [: SelectFirstGroupOfMaxLength
>>> SelectGroupsWithLeftLessThanFirstElement ) ([ ,
>>> SelectLongerOrStartsWithLonger) ]
>>>
>>> LongestIncreasingSubsequence=: [: ; [: SelectFirstGroupOfMaxLength
>>> [: > [: DoBetweenElementsInFold&.:>/ PackElements ,
>>> GroupOfEmptyGroupInitialState
>>>
>>> LongestIncreasingSubsequence=: LongestIncreasingSubsequence f.
>>>
>>>
>>> Full project of tacit version
>>>
>>> =======================
>>>
>>>
>>> NB. Find the longest stricty increasing subsequence
>>>
>>> NB. Values are the lowest last values yet found for each subsequence
>>> length.
>>>
>>> NB. Indices are the indices of these values in the original sequence.
>>>
>>> NB. Predecessors are indices to the end of the next lower subsequence
>>>
>>> NB. for each value in the original sequence.
>>>
>>> NB. The longest sequence is found by index lookup in predecessors
>>> from the index
>>>
>>> NB. of the highest found value.
>>>
>>>
>>> ts=: 6!:2 , 7!:2@] NB. Time and space
>>>
>>> Amend=:([:>[:{.[)`([:>[:{:[)`] }
>>>
>>> (1;0) Amend 3 4 5
>>>
>>> PickPower=: {~^:([`([:>[:{.])`([:>[:{:]))
>>>
>>> 2 3 4 PickPower 1;1
>>>
>>> ValuesIndicesPredecessorsIndexInitialState=: [: < a:"_ , a:"_ , (([:
>>> # ]) $2:) ;0:
>>>
>>> ValuesIndicesPredecessorsIndexInitialState 7 1 2 3
>>>
>>> PackValues=: <@+
>>>
>>> PackValues 7 1 2 3
>>>
>>> Values=: [: > 0 { ]
>>>
>>> Values 1 2 3;0 1 2;2 2 2;0
>>>
>>> Indices=: [: > 1 { ]
>>>
>>> Indices 1 2 3;0 1 2;2 2 2;0
>>>
>>> Predecessors=: [: > 2 { ]
>>>
>>> Predecessors 1 2 3;0 1 2;2 2 2;0
>>>
>>> Index=: [: > 3 { ]
>>>
>>> Index 1 2 3;0 1 2;2 2 2;0
>>>
>>> AdjustLength=: ((1 + [) >. [: # ]) {. ]
>>>
>>> 3 AdjustLength 1 2 3
>>>
>>> 2 AdjustLength 1 2 3
>>>
>>> AmendValues=: (([: {. [) ; [: {: [) Amend ([: {: [) AdjustLength Values
>>>
>>> (7,3) AmendValues 1 2 3;0 1 2;2 2 2;0
>>>
>>> AmendIndices=: (Index ; [: {: [) Amend ([: {: [) AdjustLength Indices
>>>
>>> (7,3) AmendIndices 1 2 3;0 1 2;2 2 2;0
>>>
>>> AmendPredecessors=: ((([: <: [: {: [){Indices);Index ) Amend
>>> Predecessors
>>>
>>> (7,3) AmendPredecessors 1 2 3;0 1 2;2 2 2;0
>>>
>>> DoBetweenElementsInFold=: ([,(Values I. [ )) ( [
>>> (Values;Indices;AmendPredecessors;1+Index)
>>> AmendValues;AmendIndices;Predecessors;Index) ]
>>>
>>> 3 DoBetweenElementsInFold 1 2;1 2;0 1 1 2;3
>>>
>>> Reconstruct=: [: (Predecessors PickPower ([: i. [: - [: #
>>> Indices);[: {: Indices) [: > ]
>>>
>>> Reconstruct < 1 2 3;1 2 3;0 1 1 2;4
>>>
>>> LongestIncreasingSubsequenceIndices=: [: Reconstruct [:
>>> DoBetweenElementsInFold&.:>/ ([: |. PackValues) ,
>>> ValuesIndicesPredecessorsIndexInitialState
>>>
>>> ( 7 DoBetweenElementsInFold [: >
>>> ValuesIndicesPredecessorsIndexInitialState)7 1 2 3
>>>
>>> ( 1 DoBetweenElementsInFold (7 DoBetweenElementsInFold [: >
>>> ValuesIndicesPredecessorsIndexInitialState))7 1 2 3
>>>
>>> ( 2 DoBetweenElementsInFold (1 DoBetweenElementsInFold (7
>>> DoBetweenElementsInFold [: >
>>> ValuesIndicesPredecessorsIndexInitialState)))7 1 2 3
>>>
>>> ( 3 DoBetweenElementsInFold (2 DoBetweenElementsInFold (1
>>> DoBetweenElementsInFold (7 DoBetweenElementsInFold [: >
>>> ValuesIndicesPredecessorsIndexInitialState))))7 1 2 3
>>>
>>> Reconstruct < (3 DoBetweenElementsInFold ( 2 DoBetweenElementsInFold
>>> ( 1 DoBetweenElementsInFold ( 7 DoBetweenElementsInFold [: >
>>> ValuesIndicesPredecessorsIndexInitialState))))7 1 2 3
>>>
>>> LongestIncreasingSubsequence=: ([:
>>> LongestIncreasingSubsequenceIndices ]){ ]
>>>
>>> LongestIncreasingSubsequence=: LongestIncreasingSubsequence f.
>>>
>>> LongestIncreasingSubsequence 7 1 2 3
>>>
>>> LongestIncreasingSubsequence i.0
>>>
>>> LongestIncreasingSubsequence 6 1 3 4 2 8
>>>
>>> l =: 7 4 4 5 2 7 1 8 13 2 10 4 9 1 4 5 5 4 3 10 3 4 5 8 15 7 11 19
>>>
>>> LongestIncreasingSubsequence l
>>>
>>> 9!:1 [16807
>>>
>>> [a=:LongestIncreasingSubsequence 1000?1000
>>>
>>> #a
>>>
>>> 9!:1 [16807
>>>
>>> [a=:LongestIncreasingSubsequence ?1000$1000
>>>
>>> #a
>>>
>>> ts=: 6!:2 , 7!:2@] NB. Time and space
>>>
>>> ts'LongestIncreasingSubsequence 10000?10000'
>>>
>>> ts'LongestIncreasingSubsequence ?10000$10000'
>>>
>>>
>>> ----------------------------------------------------------------------
>>> For information about J forums see http://www.jsoftware.com/forums.htm
>>
>> ----------------------------------------------------------------------
>> For information about J forums see http://www.jsoftware.com/forums.htm
>
>
> ---
> This email has been checked for viruses by Avast antivirus software.
> https://www.avast.com/antivirus
>
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
More information about the Programming
mailing list