Hunter
Hunter

Reputation: 357

Find largest 4 values of a local maximum

My program produces the following output at some timeenter image description here

and at some time later

enter image description here

and I would like to determine the largest 4 values of BOTH crests. I've managed to find the largest 4 values of the largest crest (see the code below), which is relatively simple because I basically need to find the absolute largest values. But I don't know how to find the largest 4 values of the smaller crest, and I was wondering if anybody could help me with this?


Here is the C++ code I used to find the largest 4 values of the largest crest:

for(i=0;i<4;i=i+1)
{
    queue_matrix[i] = 0.0;
}

for(i=0;i<SPACE;i=i+1)
{
    if(U_field_matrix[i][t1] > queue_matrix[0])
    {
        queue_matrix[0] = U_field_matrix[i][t1];
    }
}

for(i=0;i<SPACE;i=i+1)
{
    if((U_field_matrix[i][t1] > queue_matrix[1]) && (U_field_matrix[i][t1] < queue_matrix[0]))
    {
        queue_matrix[1] = U_field_matrix[i][t1];
    }
}

for(i=0;i<SPACE;i=i+1)
{
    if((U_field_matrix[i][t1] > queue_matrix[2]) && (U_field_matrix[i][t1] < queue_matrix[1]))
    {
        queue_matrix[2] = U_field_matrix[i][t1];
    }
}

for(i=0;i<SPACE;i=i+1)
{
    if((U_field_matrix[i][t1] > queue_matrix[3]) && (U_field_matrix[i][t1] < queue_matrix[2]))
    {
        queue_matrix[3] = U_field_matrix[i][t1];
    }
}

Upvotes: 1

Views: 148

Answers (3)

midor
midor

Reputation: 5557

I was hesitant to post this, because you seem to have a really simple usecase, which your solution probably covers sufficiently well, but there are really nicer ways to look for top-k values. In general you would probably do yourself a favor, if you split this up into a function that looks for maxima (according to what eOk said, if this works for you), a function that looks for top-k and a program which runs over your data and calls the top-k function on the surrounding values whenever it finds a maximum.

I don't have a solution like that lying around right now, and without knowing about the types of your variables, it is impossible to write one for you, but top-k for example usually looks like this for me:

#include <algorithm>
#include <vector>
template <class in_iterator, class out_iterator,                                
        class value_type = typename std::iterator_traits<in_iterator>::value_type,
        class compare = std::greater<value_type>>                               
void findTopK(in_iterator start, in_iterator end, out_iterator out,             
        size_t k)                                                               
{                                                                               
    std::vector<value_type> heap;                                               
    heap.reserve(k + 1);                                                        
    for (;start != end; ++start)                                                
    {                                                                           
        heap.push_back(*start); //min-oriented heap, order implied by compare   
        std::push_heap(std::begin(heap), std::end(heap), compare());            
        if (heap.size() > k)                                                    
        {                                                                       
            std::pop_heap(std::begin(heap), std::end(heap), compare());         
            heap.pop_back();                                                    
        }                                                                       
    }                                                                           
    while (!heap.empty())                                                       
    {                                                                           
        std::pop_heap(std::begin(heap), std::end(heap), compare());             
        *out++ = heap.back();                                                   
        heap.pop_back();                                                        
    }                                                                           
}

This method uses a heap to keep track of the k largest elements. Calling it on a regular array works as well as on any container and looks like this:

int main()                                                                      
{                                                                               
    int array[] = {1,3,4,5,6,2,62,3,32};                                        
    std::vector<int> results;                                                   
    findTopK(std::begin(array), std::end(array), back_inserter(results), 5);
}

As a result you don't have to write the k counterx loops every time, and your code becomes more readable. The difficult part for you may be providing a custom compare-function for your elements, but there are enough posts on this on so:

Custom comparator for set

Upvotes: 1

Hunter
Hunter

Reputation: 357

Inspired by @e0k's comment (thank you!), the following code will determine the largest 4 values of both crests.

for(i=0;i<SPACE;i=i+1)
{
    if((U_field_matrix[i][t1] > 0.1) && (U_field_matrix[i+1][t1]-U_field_matrix[i][t1] < 0.0))
    {
        counter1 = i;
        break;
    }
}

for(i=0;i<4;i=i+1)
{
    queue_matrix1[i] = 0.0;
}

for(i=(counter1-3);i<(counter1+4);i=i+1)
{
    if(U_field_matrix[i][t1] > queue_matrix1[0])
    {
        queue_matrix1[0] = U_field_matrix[i][t1];
    }
}

for(i=(counter1-3);i<(counter1+4);i=i+1)
{
    if((U_field_matrix[i][t1] > queue_matrix1[1]) && (U_field_matrix[i][t1] < queue_matrix1[0]))
    {
        queue_matrix1[1] = U_field_matrix[i][t1];
    }
}

for(i=(counter1-3);i<(counter1+4);i=i+1)
{
    if((U_field_matrix[i][t1] > queue_matrix1[2]) && (U_field_matrix[i][t1] < queue_matrix1[1]))
    {
        queue_matrix1[2] = U_field_matrix[i][t1];
    }
}

for(i=(counter1-3);i<(counter1+4);i=i+1)
{
    if((U_field_matrix[i][t1] > queue_matrix1[3]) && (U_field_matrix[i][t1] < queue_matrix1[2]))
    {
        queue_matrix1[3] = U_field_matrix[i][t1];
    }
}

for(i=SPACE;i>-1;i=i-1)
{
    if((U_field_matrix[i][t1] > 0.1) && (U_field_matrix[i-1][t1]-U_field_matrix[i][t1] < 0.0))
    {
        counter2 = i;
        break;
    }
}

for(i=0;i<4;i=i+1)
{
    queue_matrix2[i] = 0.0;
}

for(i=(counter2-3);i<(counter2+4);i=i+1)
{
    if(U_field_matrix[i][t1] > queue_matrix2[0])
    {
        queue_matrix2[0] = U_field_matrix[i][t1];
    }
}

for(i=(counter2-3);i<(counter2+4);i=i+1)
{
    if((U_field_matrix[i][t1] > queue_matrix2[1]) && (U_field_matrix[i][t1] < queue_matrix2[0]))
    {
        queue_matrix2[1] = U_field_matrix[i][t1];
    }
}

for(i=(counter2-3);i<(counter2+4);i=i+1)
{
    if((U_field_matrix[i][t1] > queue_matrix2[2]) && (U_field_matrix[i][t1] < queue_matrix2[1]))
    {
        queue_matrix2[2] = U_field_matrix[i][t1];
    }
}

for(i=(counter2-3);i<(counter2+4);i=i+1)
{
    if((U_field_matrix[i][t1] > queue_matrix2[3]) && (U_field_matrix[i][t1] < queue_matrix2[2]))
    {
        queue_matrix2[3] = U_field_matrix[i][t1];
    }
}

Upvotes: 0

Xavisan
Xavisan

Reputation: 53

At every graph you should find crests looking for values for x axis = i greater than value for x axis = i + 1. You will get the two crests, larger value is for larger crest. Then, compare each value with the set of values found previously

Upvotes: 0

Related Questions