[fpc-pascal] best method: multiple three state options in a decision tree

waldo kitty wkitty42 at windstream.net
Wed Jan 22 16:51:12 CET 2014


On 1/22/2014 3:52 AM, Lukasz Sokol wrote:
[...]
> ^and this...
> looks like a (good?) use for a dynamic array of TMinMaxState = [mmNone, mmMin, mmMinMax, mmMax];
> (then var Options = array[static or dynamic] of TMinMaxState;)
>
> This assumes options have a fixed position in the array however... but the bitwise code was
> assuming this anyway.

ok so basically converting 16 bits storage into an array? currently only 15 bits 
are being used and i don't know that any more will be added... but i'm not 
seeing how to add (logical AND) them together for

   optionA:mmMin AND optionC:mmMinMax

and similar up to all five basic ones as

   A:mmMin AND B:mmMax AND C:mmMinMax AND D:mmMax AND E:mmMin

> And yes, 4 states - one of them being mmNone - for the case when you don't want to use certain option.

yes, i've basically been ignoring mmNone because all the bits are off so we just 
skip over it in the ANDing code

> If there is a lot of options, but not always consecutive - so there would be a lot more of mmNone's
> than significant states (IOW the data is sparse) -

yes, with what i have done, there are 1023 valid combination... 1024 if we count 
all options off (or mmNone)... that's out of 32767 combinations where the 
majority are invalid... it is no wonder, with 1023 combinations, that i got 
lost/confused with my first attempt using if/then/else and while trying to 
manually implement the bitmap CASE code...

> maybe do
>
> TOption = record
>    Index : [whatever type would suffice here];
>    State : TMinMaxState; // [which could then be 3 state not 4]
> end;
>
> and use a dynamic array to hold the TOption(s).

as above, i'm not seeing how to AND each valid set together for later use in the 
filtering code :?

> Excuse my lameness please :) as I am not a programmer by trade.

no problems... i'm looking for ideas and input for handling items like this... i 
appreciate any input on this...

it would seem that things like this would come up a lot and that there would 
already be a class or possibly an object that one could feed the settings array 
to with the options that hold each array and then to be able to walk thru like 
one can do with TStringsList

eg: fooList:TStringsList;
     [...]
     fooList[i]:='blah';
     [...]
     writeln(fooList[i]);

i actually did look at the TBits class but didn't see an easy way of walking it 
like one can do with TStringsList... my finding and looking at TBits was after 
some 12+ hours of manually coding if/then/else, getting lost in the details and 
starting over numerous times...

what i finally did with my current attempt using a bitmapped word was to write a 
tool to generate all the code for the case statement... with this i was able to

1] find out how many valid combinations there are  (1023)
2] have the ANDs all written in the proper order for each valid bitmask
3] generate a file that is easily included {$I bitcase.inc}

any changes to the ordering need only a small rewrite to the generating tool to 
create the new CASE code for the filter... the resulting include file is only 
(!) 392353 bytes at 7932 lines with no comment lines... that's ~3x the size of 
the program's .pas file of 119151 bytes at 3157 lines with a few hundred comment 
lines...

this current implementation is used for output filtering... there's going to be 
an exact duplicate used for input selection with the only difference between the 
two CASE code blocks being the routine called on a match...

eg:
case FilterBits of
   0 : writeoutput;
   1 : begin
         if (rec^.optionA >= optionA_min) and (rec^.optionA <= optionA_max) then
           writeoutput;
       end;
   2 : begin
         if (rec^.optionA >= optionA_min) then
           writeoutput;
       end;
   3 : begin {invalid} end;
   4 : begin
         if (rec^.optionA >= optionA_max) then
           writeoutput;
       end;
[...]


case SelectBits of
   0 : addItem;
   1 : begin
         if (rec^.optionA >= optionA_min) and (rec^.optionA <= optionA_max) then
           addItem;
       end;
   2 : begin
         if (rec^.optionA >= optionA_min) then
           addItem;
       end;
   3 : begin {invalid} end;
   4 : begin
         if (rec^.optionA >= optionA_max) then
           addItem;
       end;
[...]

i think i should be able to use one routine for both input selection and output 
filtering... done by pass the bitmap and the routine to be used... that'll save 
having to worry about editing in more than one place when things change... i 
just gotta figure out how to pass the routine to use...

would something like:

   procedure runCase(var bitMap:word; whichProcedure: pointer);

called with

   runCase(SelectBits, at addItem);

   runCase(FilterBits, at writeoutput);

be the way to do this??

sometimes my linear procedural mind really gets in the way :/

-- 
NOTE: No off-list assistance is given without prior approval.
       Please keep mailing list traffic on the list unless
       private contact is specifically requested and granted.



More information about the fpc-pascal mailing list