📄 consultr.c
字号:
/*************************************************************************/
/* */
/* Classify items interactively using a set of rules */
/* ------------------------------------------------- */
/* */
/*************************************************************************/
#include "defns.i"
#include "types.i"
/* External data */
short MaxAtt, MaxClass, MaxDiscrVal;
ItemNo MaxItem;
Description *Item;
DiscrValue *MaxAttVal;
String *ClassName,
*AttName,
**AttValName,
FileName = "DF";
char *SpecialStatus;
short VERBOSITY = 0,
TRACE = 0;
Boolean FirstTime = true;
PR *Rule;
RuleNo NRules = 0,
*RuleIndex;
short RuleSpace = 0;
ClassNo DefaultClass;
/* The interview module uses a more complex description of an
case called a "Range Description" with lower and upper bounds.
For further information, see consult.c */
typedef struct ValRange *RangeDescRec;
struct ValRange
{
Boolean Known, Asked;
float LowerBound, UpperBound, *Probability;
};
RangeDescRec RangeDesc;
float Confidence;
#define MINCF 0.50 /* minimum cf for useable rule */
/*************************************************************************/
/* */
/* Find the best rule for the current case. */
/* Note: leave probability in Confidence */
/* */
/*************************************************************************/
RuleNo BestRule()
/* -------- */
{
RuleNo r;
float cf, RuleStrength();
Confidence = 0.0;
ForEach(r, 1, NRules)
{
cf = RuleStrength(Rule[r]);
if ( cf > 0.3 )
{
Confidence = cf;
return r;
}
}
return 0;
}
/*************************************************************************/
/* */
/* Given a rule, determine the strength with which we can conclude */
/* that the current case belongs to the class specified by the RHS */
/* of the rule */
/* */
/*************************************************************************/
float RuleStrength(Rule)
/* ------------ */
PR Rule;
{
short d;
float RuleProb=1.0, ProbSatisfied();
ForEach(d, 1, Rule.Size)
{
RuleProb *= ProbSatisfied(Rule.Lhs[d]);
if ( RuleProb < MINCF )
{
return 0.0;
}
}
return ( (1 - Rule.Error) * RuleProb );
}
/*************************************************************************/
/* */
/* Determine the probability of the current case description */
/* satisfying the given condition */
/* */
/*************************************************************************/
float ProbSatisfied(c)
/* ------------- */
Condition c;
{
Attribute a;
char v;
float AddProb=0.0;
Test t;
DiscrValue i;
t = c->CondTest;
a = t->Tested;
v = c->TestValue;
CheckValue(a, Nil);
if ( ! RangeDesc[a].Known )
{
return 0.0;
}
switch ( t->NodeType )
{
case BrDiscr: /* test of discrete attribute */
return RangeDesc[a].Probability[v];
case ThreshContin: /* test of continuous attribute */
if ( RangeDesc[a].UpperBound <= t->Cut )
{
return ( v == 1 ? 1.0 : 0.0 );
}
else
if ( RangeDesc[a].LowerBound > t->Cut )
{
return ( v == 2 ? 1.0 : 0.0 );
}
else
if ( v == 1 )
{
return (t->Cut - RangeDesc[a].LowerBound) /
(RangeDesc[a].UpperBound - RangeDesc[a].LowerBound);
}
else
{
return (RangeDesc[a].UpperBound - t->Cut) /
(RangeDesc[a].UpperBound - RangeDesc[a].LowerBound);
}
case BrSubset: /* subset test on discrete attribute */
ForEach(i, 1, MaxAttVal[a])
{
if ( In(i, t->Subset[v]) )
{
AddProb += RangeDesc[a].Probability[i];
}
}
return AddProb;
}
return 0.0;
}
/*************************************************************************/
/* */
/* Process a single case */
/* */
/*************************************************************************/
InterpretRuleset()
/* ---------------- */
{
char Reply;
Attribute a;
RuleNo r;
/* Initialise */
ForEach(a, 0, MaxAtt)
{
RangeDesc[a].Asked = false;
}
if ( FirstTime )
{
FirstTime = false;
printf("\n");
}
else
{
printf("\n-------------------------------------------\n\n");
}
/* Find the first rule that fires on the item */
if ( r = BestRule() )
{
printf("\nDecision:\n");
printf("\t%s", ClassName[Rule[r].Rhs]);
if ( Confidence < 1.0 )
{
printf(" CF = %.2f", Confidence);
}
printf("\n");
}
else
{
printf("\nDecision:\n");
printf("\t%s (default class)\n", ClassName[DefaultClass]);
}
/* Prompt for what to do next */
while ( true )
{
printf("\nRetry, new case or quit [r,n,q]: ");
Reply = getchar();
SkipLine(Reply);
switch ( Reply )
{
case 'r': return;
case 'n': Clear(); return;
case 'q': exit(0);
default: printf("Please enter 'r', 'n' or 'q'");
}
}
}
/*************************************************************************/
/* */
/* Main routine for classifying items using a set of rules */
/* */
/*************************************************************************/
main(Argc, Argv)
/* ---- */
int Argc;
char *Argv[];
{
int o;
extern char *optarg;
extern int optind;
Attribute a;
RuleNo r;
PrintHeader("production rule interpreter");
/* Process options */
while ( (o = getopt(Argc, Argv, "tvf:")) != EOF )
{
switch (o)
{
case 't': TRACE = 1;
break;
case 'v': VERBOSITY = 1;
break;
case 'f': FileName = optarg;
break;
case '?': printf("unrecognised option\n");
exit(1);
}
}
/* Initialise */
GetNames();
GetRules();
if ( TRACE )
{
ForEach(r, 1, NRules)
{
PrintRule(r);
}
printf("\nDefault class: %s\n", ClassName[DefaultClass]);
}
/* Allocate value ranges */
RangeDesc = (struct ValRange *) calloc(MaxAtt+1, sizeof(struct ValRange));
ForEach(a, 0, MaxAtt)
{
if ( MaxAttVal[a] )
{
RangeDesc[a].Probability =
(float *) calloc(MaxAttVal[a]+1, sizeof(float));
}
}
/* Consult */
Clear();
while ( true )
{
InterpretRuleset();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -