[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