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

Lukasz Sokol el.es.cr at gmail.com
Wed Jan 22 18:12:27 CET 2014


On 22/01/14 15:51, waldo kitty wrote:
> 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.


If you insist on using bits.... define them:

const
  OptionAmmMin = $0001;
  OptionAmmMinMax = $0002;
  OptionAmmMax = $0004; // and so on


then do

if Options and (OptionAmmMin and ... ) then 

?

I would have thought, that having an array of TOption like I wrote, would 
ensure the exclusivity.
And having the array dynamic, you can check for its size, then write some clever code to use it ;)

> 
> 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...

If you count permutations (so combinations not repeating) you'd have 120 valid ones...?
http://easycalculation.com/statistics/permutation-combination.php
do I understand that correctly?

>> 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 :/
> 

Huh, well a lot of micro-management goes on here;

What if you did it like:

- define the valid bit masks (permutations?) at the start, dynamically
- associate the procedures (their pointers) to jump to with the valid bit masks in a new data type
(- do you REALLY have that many procedures ? Or are they somewhat repeating themselves ?)
- then just walk the array of [bit mask, proc pointer] records and jump to pointers supplied if matching?

No ifs, no buts, treat the Options as a bitmask if such is its purpose?

Just a thought,
-L.




More information about the fpc-pascal mailing list