LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Perl script for linear interpolation (https://www.linuxquestions.org/questions/programming-9/perl-script-for-linear-interpolation-4175445813/)

eminempark 01-16-2013 02:33 AM

Perl script for linear interpolation
 
May I know the code to apply linear interpolation in my data? For example, I have a data
Code:

#X Y
1 1
3 9
5 25
9 81

By using the linear interpolation in perl, my output should be
Code:

#X Y
1 1
2 5
3 9
4 18
5 25
6 39
7 53
8 67
9 81

Currently I have this code, but it wont run...
Code:

#! /usr/bin/perl -w
use strict;

my $prev_id = 0;
my $prev_val = 0;
my $next_id;
my $next_val;

while (<>)
{
    my ($id, $val) = split;
    for (my $i = $prev_id + 1; $i < $next_id; $i++)
    {
        $val = (($id - $next_id) / ($prev_id - $next_id)) * $prev_val + (($id - $prev_id) / ($next_id - $prev_id)) * $next_val;
        printf ("%d %s\n", $i, $val);
    }
    printf ("%d %s\n", $id, $val);
    ($prev_val, $prev_id) = ($val, $id);
    ($next_val, $next_id) = ($prev_val, $prev_id); 
}

Help me.. Thanks

millgates 01-16-2013 03:49 AM

You have a huge mess in your variables and the logic of your code. You use the values of the variables before you initialize them. You use the wrong variables to hold the wrong values.
What is $val and $id?
What is $prev_val and $prev_id?
What is $next_val and $next_id?

also, you should put a line there to handle the first line (comment)

btw, a very creative way of computing linear interpolation. :)

eminempark 01-16-2013 06:25 AM

Quote:

Originally Posted by millgates (Post 4871171)
You have a huge mess in your variables and the logic of your code. You use the values of the variables before you initialize them. You use the wrong variables to hold the wrong values.
What is $val and $id?
What is $prev_val and $prev_id?
What is $next_val and $next_id?

also, you should put a line there to handle the first line (comment)

btw, a very creative way of computing linear interpolation. :)

$ID is the current ID that need to fill in, it probably exists or does not exist.
$val is the current value that need to fill in, it probably exists or does not exist.
$prev_val is the previous existing value.
$prev_ID is the previous existing ID.
$next_val is the next existing value.
$next_ID is the next existing ID.

Any idea?

millgates 01-16-2013 06:43 AM

As I implied, the problem is you confuse the variables.
OK, let's go through the code, then

Code:

my ($id, $val) = split;
So, you assign the new values to $id and $val.

Code:

for (my $i = $prev_id + 1; $i < $next_id; $i++)
Here, you iterate over $i. What is the purpose of $i, anyway?

Code:

$val = (($id - $next_id) / ($prev_id - $next_id)) * $prev_val + (($id - $prev_id) / ($next_id - $prev_id)) * $next_val;
The basic idea behind this is OK, but how comes nothing here depends on the variable $i you iterate over? You just keep computing this with the same set of values each time.
Also, $next_id and $next_val are not defined yet (at least in the first iteration).

Code:

($prev_val, $prev_id) = ($val, $id);
What are the values of $val and $id at this point?

Code:

($next_val, $next_id) = ($prev_val, $prev_id);
What is your reasoning behind this line?

eminempark 01-16-2013 07:14 AM

Quote:

Originally Posted by millgates (Post 4871267)
As I implied, the problem is you confuse the variables.
OK, let's go through the code, then

Code:

my ($id, $val) = split;
So, you assign the new values to $id and $val.

Code:

for (my $i = $prev_id + 1; $i < $next_id; $i++)
Here, you iterate over $i. What is the purpose of $i, anyway?

Code:

$val = (($id - $next_id) / ($prev_id - $next_id)) * $prev_val + (($id - $prev_id) / ($next_id - $prev_id)) * $next_val;
The basic idea behind this is OK, but how comes nothing here depends on the variable $i you iterate over? You just keep computing this with the same set of values each time.
Also, $next_id and $next_val are not defined yet (at least in the first iteration).

Code:

($prev_val, $prev_id) = ($val, $id);
What are the values of $val and $id at this point?

Code:

($next_val, $next_id) = ($prev_val, $prev_id);
What is your reasoning behind this line?

$i basically used for the reformed ID.
the main problem is $next_id and $next_val because it depends on the next existing value.
the $val and $id is the existing value and existing ID.

millgates 01-16-2013 08:07 AM

Think about your algorithm a bit.
What you need for each interval, is id and value for both
1) the begining of the interval (you need to remember that from the previous iteration) and
2) the end of the interval (which is what you have just read from the input file).
In the for loop, you interpolate values for all ids between the begining and end of the interval.
In the end you just need to remember the last id and value processed, which happens to be the end of the interval. These will become the begining of the interval for the next iteration.
That's all there is to it. Don't make it more complicated than it needs to be.

eminempark 01-17-2013 12:10 AM

Quote:

Originally Posted by millgates (Post 4871331)
Think about your algorithm a bit.
What you need for each interval, is id and value for both
1) the begining of the interval (you need to remember that from the previous iteration) and
2) the end of the interval (which is what you have just read from the input file).
In the for loop, you interpolate values for all ids between the begining and end of the interval.
In the end you just need to remember the last id and value processed, which happens to be the end of the interval. These will become the begining of the interval for the next iteration.
That's all there is to it. Don't make it more complicated than it needs to be.

Here is the updated one... Any Idea?
Code:

#! /usr/bin/perl -w
use strict;

my ($prev_id, $prev_val) = (0,0);

while (<>)
{
  my ($id, $val) = split;
  for( my $temp_id=$prev_id+1; $prev_id>0 && $temp_id<$id; $temp_id++ )
  {
    printf( "*%s is between %s(%s) and %s(%s) <- all numbers required to generate value, use them!\n", $temp_id, $prev_id, $prev_val, $id, $val );
  }
  printf( "%d %s\n", $id, $val );
  ($prev_id, $prev_val) = ($id, $val);
}


millgates 01-17-2013 01:59 AM

So, what is the problem with it? Doesn't it do what you want?
Where has the interpolation gone?

eminempark 01-17-2013 02:57 AM

Quote:

Originally Posted by millgates (Post 4871951)
So, what is the problem with it? Doesn't it do what you want?
Where has the interpolation gone?

Partially is what I want, because i do not know how to apply the interpolation...

millgates 01-17-2013 03:16 AM

Same as before, only instead of $id use $temp_id and instead of $next_id use $id

Sergei Steshenko 01-20-2013 03:43 PM

Quote:

Originally Posted by eminempark (Post 4871985)
... i do not know how to apply the interpolation...

?????????????

Interpolation is a function/formula. Have you looked up what interpolation is in the first place ? Regardless of Perl.

eminempark 01-21-2013 12:42 AM

Quote:

Originally Posted by Sergei Steshenko (Post 4874262)
?????????????

Interpolation is a function/formula. Have you looked up what interpolation is in the first place ? Regardless of Perl.

I use this awk to solve the linear interpolation. For sure, I understand what is the meaning of linear interpolation.
Code:

awk '
{
  P[$1]=$2
  I[i++]=$1
}
END{
  j=0; s=I[j]; t=I[j+1]
  for(i=m;i<=n;i++){
    if(I[j+2] && i>t){
      j++; s=I[j]; t=I[j+1]
    }                       
    print i,P[s]+(i-s)*(P[t]-P[s])/(t-s)
  }                                   
}
' m=1001 n=1100 infile



All times are GMT -5. The time now is 06:04 PM.