Hi Steve, Edson, and all,

I'm happy with setting bias = 0.42, given that several quite different 
tests show that it results in a rate of false decodes smaller than 1 in 
1000.

As for reporting to WSPRnet: my preference is to report all decodes to 
the database site. It's not so very unusual for a new callsign to turn 
up -- perhaps to be decoded only once, especially if band-hopping is in 
use.  The occasional long distance paths with unusual propagation can be 
especially interesting, even (or especially?) when they are one-off 
events.  It's relatively easy to and apply further sanitizing of data at 
the database site, or elsewhere when any analysis of the data is done.
        -- Joe, K1JT

On 8/1/2015 7:33 PM, Steven Franke wrote:
> Hi Joe,
>
>> On Aug 1, 2015, at 1:02 PM, Joe Taylor<j...@princeton.edu>  wrote:
>>
>> Hi Steve,
>>
>> Visiting family are arriving later than expected, so I found some
>> unexpected time to play with wsprd and wsprd_exp.  To make the KA9Q fano
>> decoder work with your change, I had to increase the size of the node[]
>> structure by one bit:
>
>>
>
> Oops - you are right. Why didn’t I get into trouble? Presumably, there was 
> some slack space after the malloc that allowed me to write outside of the 
> allocation without clobbering anything?
>
>> ##############################################################################
>>
>> pulsar:~/jtsdk/src/wsjtx/lib/wsprd$ svn diff
>> Index: fano.c
>> ===================================================================
>> --- fano.c      (revision 5745)
>> +++ fano.c      (working copy)
>> @@ -105,7 +105,7 @@
>>     unsigned int lsym;
>>     unsigned int i;
>>
>> -  if((nodes = (struct node *)malloc(nbits*sizeof(struct node))) == NULL) {
>> +  if((nodes = (struct node *)malloc((nbits+1)*sizeof(struct node))) ==
>> NULL) {
>>       printf("malloc failed\n");
>>       return 0;
>>     }
>> @@ -172,7 +172,7 @@
>>         }
>>         np[1].gamma = ngamma;                     // Move forward
>>         np[1].encstate = np->encstate<<  1;
>> -      if(++np == lastnode) {
>> +      if(++np == lastnode+1) {
>>          break;                                  // Done!
>>         }
>> ##############################################################################
>>
>>
>> Here are some new results, which essentially confirm your findings.
>> Both programs (wsprd and wsprd_exp) were compiled with the above changes
>> made to fano.c.  Just for fun, I timed each run separately after
>> compilation with clang-3.5 and gcc.
>>
>>     Command                         T   B   G  Time  Time
>>                                               clang   gcc
>> ---------------------------------------------------------------
>> 1. wsprd                          124  0  124  25.1  24.2
>> 2. wsprd_exp                      130  7  123  33.7  32.2
>> 3. wsprd_exp -J -C 5000           125  3  122  33.1  32.3
>> 4. wsprd_exp -z 0.46              122  0  122  34.8  33.3
>> 5. wsprd_exp -z 0.46 -J -C 5000   122  0  122  33.8  33.5
>> 6. wsprd_exp -z 0.5               120  0  120  34.6  33.3
>> 7. wsprd_exp -z 0.5 -J -C 5000    119  0  119  34.0  33.1
>>
>> T = total decodes
>> B = bad decodes
>> G = good decodes
>>
>> Some history concerning fano.c may be informative.  Phil Karn's code had
>>
>>          tail =&nodes[nbits-33];
>>
>> where we now have
>>
>>          tail =&nodes[nbits-31];
>>
>> I made this change a long time ago, for reasons that seemed right to me
>> at the time.  Probably I should also have changed the "Done" condition
>> as you have now done.
>>
>> Why did I need to increase the memory allocation for nodes, while you
>> did not?  Possibly the whole thing is not quite right, yet, though your
>> test on the final metric seems to indicate that it's OK.
>
> I think that it’s working correctly now. At least, it is visiting the same 
> nodes and coming up with the same path metrics as Jelinek. And the Jelinek 
> algorithm is so simple that I’m pretty sure that it’s doing the right thing.
>
> I find the fano.c book-keeping approach confusing (though it makes sense from 
> an efficiency/execution time point of view). Specifically, in fano.c each 
> node entry stores an encoder state that includes up to the i’th bit, but it 
> stores the metric only up through the previous (i-1)th bit.
>
> This quirk is why we need to malloc space for one extra node, because the 
> final metric (for the 81-bit long frame) is actually stored in the 82nd entry 
> of the node[] struct array...
>
> Jelinek works differently - because it never backtracks, it can efficiently 
> store the i’th bit and the metric up through the i’th bit in the same node.
>
>>
>>
>> One more thing escapes me at the moment.  Why does case 2 give different
>> results from case 1?  They both use the corrected fano decoder with
>> maxcycles=10000 and bias=0.42.
>
> wsprd_exp uses a different sync algorithm - basically a nested-grid approach 
> in an attempt to improve the efficiency of the sync search. It also tries to 
> refine the drift estimate. This means that the candidate symbol vectors that 
> are submitted to the decoder are somewhat different in wsprd and wsprd_exp. 
> Up until I saw your files I was convinced that wsprd_exp was the superior 
> sync algorithm. Now, not so much.
>
> I’m happy with how fano.c is behaving now. I intend to make the 
> malloc/lastnode changes unless I hear otherwise.
>
> Perhaps we should turn attention to the philosophical question of where to 
> set the bias. I ran some simulations to study how bias affects the 
> probability of decode and probability of bad decode under controlled 
> conditions.
>
> First I ran tests using wsprsim-generated files with -31 dB snr to test the 
> effect of the change in the fano decoder. For each simulation run I generated 
> and decoded 10000 .c2 files. Since all simulated files have the message “K9AN 
> EN50 33”, it was easy to find and count all frames with errors, not just the 
> ones with a forward slash. Here are the results:
>
> wsprd (original fano.c, bias=0.42)
> 5599 decodes, 25 bad decodes (13 bad with “/“), in 1750s (total of 5574 good 
> decodes, 55.7%)
>
> wsprd (modified fano.c, bias=0.42)
> 5578 decodes, 17 bad decodes (4 bad with “/“), in 2225s (total of 5571 good 
> decodes, 55.7%)
>
> This shows that decoding the 81st zero decreased the probability of a bad 
> frame by 33% while having a negligible affect on the probability of 
> successfully decoding a frame.
>
> If, in addition, we raise the bias to 0.46:
>
> wsprd (modified fano.c, bias=0.46)
> 4690 decodes, 8 bad decodes (1 bad with “/“), in 2510s
>
> And with bias=0.50 wsprd (modified fano.c)
> 4174 decodes, 3 bad decodes (1 bad with “/“), in 2669s
>
> In raising the bias from 0.42 to 0.46 we lose more than 900 good decodes just 
> to suppress 9 bad decodes, a 100:1 ratio. From 0.42 to 0.50 we lose more than 
> 1400 to suppress 14 bad ones - still 100:1. Personally, I don’t like to give 
> away so many good decodes.
>
> This brings me back to Edson’s suggestion… Why not run with low bias and just 
> use Edson’s mechanism to filter what gets sent to wsprnet.org?
>
> Steve k9an
>
>
>>
>>      -- Joe
>>
>> On 7/31/2015 11:45 PM, Steven Franke wrote:
>>> Joe,
>>>
>>>> On these files I ran test cases like yours, plus two more, with the
>>>> following results:
>>>>
>>>>     Command                         T   B   G  time
>>>> -----------------------------------------------------------
>>>> 1. wsprd                          125  2  123  25 s
>>>> 2. wsprd_exp                      126 13  113  29
>>>> 3. wsprd_exp -J -C 5000           115  3  112  30
>>>> 4. wsprd_exp -J -C 5000 -z 0.5    112  0  112  30
>>>> 5. wsprd_exp -z 0.5               113  1  112  30
>>>> 6. wsprd5000                      120  0  120  23
>>>> 7. wsprd -z 0.5                   119  0  119  26
>>>>
>>>> T = total decodes
>>>> B = bad decodes
>>>> G = good decodes
>>>>
>>>> Case #6 used a re-compiled wsprd with maxcycles=5000.
>>>>
>>>> On these files, at least, it seems that the best performer is the
>>>> deafult wsprd, Case #1: 123 good decodes, 2 false decodes.  With
>>>> maxcycles=5000 (Case #6) it yields 120 good decodes and 0 false decodes.
>>>>   With bias=0.5 (Case #7) it gives 119 good decodes and 0 false decodes.
>>>>
>>>> Seems to me we should probably go back to bias=0.5, and possibly reduce
>>>> maxcycles a bit.
>>>
>>> I’m on the same page regarding the need to decrease the number of 
>>> bit-errors in the decoded frames. But the thing that has been bothering me 
>>> the most is the vastly different results from Fano and Jelinek when 
>>> presented with the same candidates. All of my background reading suggests 
>>> that these two algorithms should visit the same nodes, given enough cycles. 
>>> And yet, I was unable to get Jelinek to produce the same bad decodes, even 
>>> when I allowed a huge number of cycles and a huge stack size. So I’ve been 
>>> suspicious about a programming error or bug.
>>>
>>> I think that I’ve found at least a partial explanation for the bad behavior 
>>> of Fano. I’ve concluded that fano.c, as configured, is not decoding all 31 
>>> tail bits. It is stopping at 30 bits. I discovered this after printing out 
>>> the final metric for decoded frames. I noticed that on a clean high-snr 
>>> test file, as generated by wsprsim, the final metric for a Fano decode was 
>>> 800, whereas it is 810 for Jelinek. Similarly all of the final metrics 
>>> produced by Fano were smaller than those produced by Jelinek.
>>>
>>> The following change makes the high-snr final metric 810 for Fano, and in 
>>> fact makes all final metrics from Fano and Jelinek identical:
>>>
>>> $ svn diff
>>> Index: wsprd/fano.c
>>> ===================================================================
>>> --- wsprd/fano.c    (revision 5740)
>>> +++ wsprd/fano.c    (working copy)
>>> @@ -172,7 +172,7 @@
>>>         }
>>>         np[1].gamma = ngamma;                     // Move forward
>>>         np[1].encstate = np->encstate<<   1;
>>> -      if(++np == lastnode) {
>>> +      if(++np == lastnode+1) {
>>>     break;                                  // Done!
>>>         }
>>>
>>>
>>> With this change, the results for cases 1 and 2 improve to:
>>> 1.wsprd 124 0 124
>>> 2. wsprd_exp 130 7 123 (compare to your case 2 — it is counter to my 
>>> intuition that we get more good decodes by decoding further into the tail)
>>>
>>> Also, I got different results for your case 3. This shouldn’t be affected 
>>> by the fano.c change, so I wonder if you just mis-copied the numbers on 
>>> this one:
>>>
>>> 3. wsprd_exp -JC 5000 125 3 122
>>>
>>> Finally, note that a metric bias of 0.46 eliminates bad decodes with either 
>>> decoder in wsprd_exp (using the modified fano.c):
>>> wsprd_exp -z 0.46 122 (0) in 19s
>>> wsprd_exp -Jz 0.46 -C 5000 122 (0) in 19s
>>>
>>> So - at this point I am inclined to make the change to fano.c so that we 
>>> decode all 31 tail zeros (provided that you agree with my interpretation of 
>>> what’s going on). I’m also inclined to raise the default bias in wsprd to 
>>> at least 0.46. Or even 0.5 if you prefer, though this may be less necessary 
>>> with the fano fix.
>>>
>>> I also like Edson’s idea. I think that his suggestion could be a win-win by 
>>> essentially eliminating bad decodes in the database and allowing us to run 
>>> a little closer to the ragged edge in terms of what is displayed locally. I 
>>> imagine that spots that are not in ALL_WSPR and therefore are not 
>>> uploadable could be displayed in a different color to make it clear that 
>>> they are only for local consumption.
>>>
>>> Steve k9an
>>>
>>>>
>>>>    -- Joe
>>>>
>>>> ------------------------------------------------------------------------------
>>>> _______________________________________________
>>>> wsjt-devel mailing list
>>>> wsjt-devel@lists.sourceforge.net
>>>> https://lists.sourceforge.net/lists/listinfo/wsjt-devel
>>>
>>>
>>> ------------------------------------------------------------------------------
>>> _______________________________________________
>>> wsjt-devel mailing list
>>> wsjt-devel@lists.sourceforge.net
>>> https://lists.sourceforge.net/lists/listinfo/wsjt-devel
>>
>> ------------------------------------------------------------------------------
>> _______________________________________________
>> wsjt-devel mailing list
>> wsjt-devel@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/wsjt-devel
>
>
> ------------------------------------------------------------------------------
> _______________________________________________
> wsjt-devel mailing list
> wsjt-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/wsjt-devel

------------------------------------------------------------------------------
_______________________________________________
wsjt-devel mailing list
wsjt-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wsjt-devel

Reply via email to