[26] | 1 | /*************************************************************************/ |
---|
| 2 | /* */ |
---|
| 3 | /* User interface for consulting trees and rulesets */ |
---|
| 4 | /* ------------------------------------------------ */ |
---|
| 5 | /* */ |
---|
| 6 | /*************************************************************************/ |
---|
| 7 | |
---|
| 8 | |
---|
| 9 | #include "defns.i" |
---|
| 10 | #include "types.i" |
---|
| 11 | #include "extern.i" |
---|
| 12 | |
---|
| 13 | |
---|
| 14 | typedef struct ValRange *RangeDescRec; |
---|
| 15 | struct ValRange |
---|
| 16 | { |
---|
| 17 | Boolean Known, Asked; |
---|
| 18 | float LowerBound, UpperBound, *Probability; |
---|
| 19 | }; |
---|
| 20 | |
---|
| 21 | extern RangeDescRec RangeDesc; |
---|
| 22 | |
---|
| 23 | |
---|
| 24 | #define Fuzz 0.01 |
---|
| 25 | |
---|
| 26 | |
---|
| 27 | /*************************************************************************/ |
---|
| 28 | /* */ |
---|
| 29 | /* Ask for the value of attribute Att if necessary */ |
---|
| 30 | /* */ |
---|
| 31 | /*************************************************************************/ |
---|
| 32 | |
---|
| 33 | |
---|
| 34 | CheckValue(Att, T) |
---|
| 35 | /* ---------- */ |
---|
| 36 | Attribute Att; |
---|
| 37 | Tree T; |
---|
| 38 | { |
---|
| 39 | if ( RangeDesc[Att].Asked ) return; |
---|
| 40 | |
---|
| 41 | printf("%s", AttName[Att]); |
---|
| 42 | if ( RangeDesc[Att].Known ) |
---|
| 43 | { |
---|
| 44 | printf(" [ "); |
---|
| 45 | PrintRange(Att); |
---|
| 46 | printf(" ]"); |
---|
| 47 | } |
---|
| 48 | printf(": "); |
---|
| 49 | |
---|
| 50 | ReadRange(Att, T); |
---|
| 51 | } |
---|
| 52 | |
---|
| 53 | |
---|
| 54 | |
---|
| 55 | /*************************************************************************/ |
---|
| 56 | /* */ |
---|
| 57 | /* Print the range of values for attribute Att */ |
---|
| 58 | /* */ |
---|
| 59 | /*************************************************************************/ |
---|
| 60 | |
---|
| 61 | |
---|
| 62 | PrintRange(Att) |
---|
| 63 | /* ----------- */ |
---|
| 64 | Attribute Att; |
---|
| 65 | { |
---|
| 66 | DiscrValue dv; |
---|
| 67 | Boolean First=true; |
---|
| 68 | float p; |
---|
| 69 | |
---|
| 70 | if ( MaxAttVal[Att] ) /* discrete attribute */ |
---|
| 71 | { |
---|
| 72 | ForEach(dv, 1, MaxAttVal[Att] ) |
---|
| 73 | { |
---|
| 74 | if ( (p = RangeDesc[Att].Probability[dv]) > Fuzz ) |
---|
| 75 | { |
---|
| 76 | if ( ! First ) |
---|
| 77 | { |
---|
| 78 | printf(", "); |
---|
| 79 | } |
---|
| 80 | First = false; |
---|
| 81 | |
---|
| 82 | printf("%s", AttValName[Att][dv]); |
---|
| 83 | if ( p < 1-Fuzz ) |
---|
| 84 | { |
---|
| 85 | printf(": %.2f", p); |
---|
| 86 | } |
---|
| 87 | } |
---|
| 88 | } |
---|
| 89 | } |
---|
| 90 | else /* continuous attribute */ |
---|
| 91 | { |
---|
| 92 | printf("%g", RangeDesc[Att].LowerBound); |
---|
| 93 | if ( RangeDesc[Att].UpperBound > RangeDesc[Att].LowerBound + Fuzz ) |
---|
| 94 | { |
---|
| 95 | printf(" - %g", RangeDesc[Att].UpperBound); |
---|
| 96 | } |
---|
| 97 | } |
---|
| 98 | } |
---|
| 99 | |
---|
| 100 | |
---|
| 101 | |
---|
| 102 | extern char Delimiter; |
---|
| 103 | #define SkipSpace while ( (c = getchar()) == ' ' || c == '\t' ) |
---|
| 104 | |
---|
| 105 | |
---|
| 106 | /*************************************************************************/ |
---|
| 107 | /* */ |
---|
| 108 | /* Read a range of values for attribute Att or <cr> */ |
---|
| 109 | /* */ |
---|
| 110 | /*************************************************************************/ |
---|
| 111 | |
---|
| 112 | |
---|
| 113 | ReadRange(Att, T) |
---|
| 114 | /* ---------- */ |
---|
| 115 | Attribute Att; |
---|
| 116 | Tree T; |
---|
| 117 | { |
---|
| 118 | char c; |
---|
| 119 | |
---|
| 120 | RangeDesc[Att].Asked=true; |
---|
| 121 | |
---|
| 122 | SkipSpace; |
---|
| 123 | |
---|
| 124 | if ( c == '\n' ) |
---|
| 125 | { |
---|
| 126 | return; |
---|
| 127 | } |
---|
| 128 | if ( c == '?' ) |
---|
| 129 | { |
---|
| 130 | if ( (c = getchar()) == 't' ) |
---|
| 131 | { |
---|
| 132 | if ( T ) PrintTree(T); |
---|
| 133 | SkipLine(c); |
---|
| 134 | RangeDesc[Att].Asked = false; |
---|
| 135 | CheckValue(Att, T); |
---|
| 136 | } |
---|
| 137 | else |
---|
| 138 | { |
---|
| 139 | RangeDesc[Att].Known = false; |
---|
| 140 | SkipLine(c); |
---|
| 141 | } |
---|
| 142 | return; |
---|
| 143 | } |
---|
| 144 | |
---|
| 145 | ungetc(c, stdin); |
---|
| 146 | RangeDesc[Att].Known = true; |
---|
| 147 | |
---|
| 148 | if ( MaxAttVal[Att] ) |
---|
| 149 | { |
---|
| 150 | ReadDiscr(Att, T); |
---|
| 151 | } |
---|
| 152 | else |
---|
| 153 | { |
---|
| 154 | ReadContin(Att, T); |
---|
| 155 | } |
---|
| 156 | } |
---|
| 157 | |
---|
| 158 | |
---|
| 159 | |
---|
| 160 | /*************************************************************************/ |
---|
| 161 | /* */ |
---|
| 162 | /* Read a discrete attribute value or range */ |
---|
| 163 | /* */ |
---|
| 164 | /*************************************************************************/ |
---|
| 165 | |
---|
| 166 | ReadDiscr(Att, T) |
---|
| 167 | /* --------- */ |
---|
| 168 | Attribute Att; |
---|
| 169 | Tree T; |
---|
| 170 | { |
---|
| 171 | char Name[500]; |
---|
| 172 | Boolean ReadName(); |
---|
| 173 | DiscrValue dv, PNo; |
---|
| 174 | float P, PSum; |
---|
| 175 | |
---|
| 176 | ForEach(dv, 1, MaxAttVal[Att]) |
---|
| 177 | { |
---|
| 178 | RangeDesc[Att].Probability[dv] = 0.0; |
---|
| 179 | } |
---|
| 180 | |
---|
| 181 | do |
---|
| 182 | { |
---|
| 183 | ReadName(stdin, Name); |
---|
| 184 | |
---|
| 185 | dv = Which(Name, AttValName[Att], 1, MaxAttVal[Att]); |
---|
| 186 | if ( ! dv ) |
---|
| 187 | { |
---|
| 188 | printf("\tPermissible values are %s", AttValName[Att][1]); |
---|
| 189 | ForEach(dv, 2, MaxAttVal[Att]) |
---|
| 190 | { |
---|
| 191 | printf(", %s", AttValName[Att][dv]); |
---|
| 192 | } |
---|
| 193 | printf("\n"); |
---|
| 194 | |
---|
| 195 | SkipLine(Delimiter); |
---|
| 196 | Retry(Att, T); |
---|
| 197 | return; |
---|
| 198 | } |
---|
| 199 | |
---|
| 200 | if ( Delimiter == ':' ) |
---|
| 201 | { |
---|
| 202 | ReadName(stdin, Name); |
---|
| 203 | sscanf(Name, "%f", &P); /* get probability */ |
---|
| 204 | } |
---|
| 205 | else |
---|
| 206 | { |
---|
| 207 | P = 1.0; /* only one attribute value */ |
---|
| 208 | } |
---|
| 209 | |
---|
| 210 | RangeDesc[Att].Probability[dv] = P; |
---|
| 211 | } |
---|
| 212 | while ( Delimiter == ',' ); |
---|
| 213 | |
---|
| 214 | /* Check that sum of probabilities is not > 1 */ |
---|
| 215 | |
---|
| 216 | PNo = MaxAttVal[Att]; |
---|
| 217 | PSum = 1.0; |
---|
| 218 | ForEach(dv, 1, MaxAttVal[Att]) |
---|
| 219 | { |
---|
| 220 | if ( RangeDesc[Att].Probability[dv] > Fuzz ) |
---|
| 221 | { |
---|
| 222 | PSum -= RangeDesc[Att].Probability[dv]; |
---|
| 223 | PNo--; |
---|
| 224 | } |
---|
| 225 | } |
---|
| 226 | |
---|
| 227 | if ( PSum < 0 || ! PNo && PSum > Fuzz ) |
---|
| 228 | { |
---|
| 229 | printf("Probability values must sum to 1\n"); |
---|
| 230 | SkipLine(Delimiter); |
---|
| 231 | Retry(Att, T); |
---|
| 232 | return; |
---|
| 233 | } |
---|
| 234 | |
---|
| 235 | /* Distribute the remaining probability equally among |
---|
| 236 | the unspecified attribute values */ |
---|
| 237 | |
---|
| 238 | PSum /= PNo; |
---|
| 239 | ForEach(dv, 1, MaxAttVal[Att]) |
---|
| 240 | { |
---|
| 241 | if ( RangeDesc[Att].Probability[dv] < Fuzz ) |
---|
| 242 | { |
---|
| 243 | RangeDesc[Att].Probability[dv] = PSum; |
---|
| 244 | } |
---|
| 245 | } |
---|
| 246 | } |
---|
| 247 | |
---|
| 248 | |
---|
| 249 | |
---|
| 250 | /*************************************************************************/ |
---|
| 251 | /* */ |
---|
| 252 | /* Read a continuous attribute value or range */ |
---|
| 253 | /* */ |
---|
| 254 | /*************************************************************************/ |
---|
| 255 | |
---|
| 256 | |
---|
| 257 | ReadContin(Att, T) |
---|
| 258 | /* ---------- */ |
---|
| 259 | Attribute Att; |
---|
| 260 | Tree T; |
---|
| 261 | { |
---|
| 262 | char c; |
---|
| 263 | |
---|
| 264 | scanf("%f", &RangeDesc[Att].LowerBound); |
---|
| 265 | SkipSpace; |
---|
| 266 | |
---|
| 267 | if ( c == '-' ) |
---|
| 268 | { |
---|
| 269 | scanf("%f", &RangeDesc[Att].UpperBound); |
---|
| 270 | SkipSpace; |
---|
| 271 | } |
---|
| 272 | else |
---|
| 273 | { |
---|
| 274 | RangeDesc[Att].UpperBound = RangeDesc[Att].LowerBound; |
---|
| 275 | } |
---|
| 276 | |
---|
| 277 | if ( c != '\n' ) |
---|
| 278 | { |
---|
| 279 | printf("Must be a continuous value or range\n"); |
---|
| 280 | SkipLine(c); |
---|
| 281 | Retry(Att, T); |
---|
| 282 | } |
---|
| 283 | } |
---|
| 284 | |
---|
| 285 | |
---|
| 286 | |
---|
| 287 | /*************************************************************************/ |
---|
| 288 | /* */ |
---|
| 289 | /* Try again to obtain a value for attribute Att */ |
---|
| 290 | /* */ |
---|
| 291 | /*************************************************************************/ |
---|
| 292 | |
---|
| 293 | Retry(Att, T) |
---|
| 294 | /* ----- */ |
---|
| 295 | Attribute Att; |
---|
| 296 | Tree T; |
---|
| 297 | { |
---|
| 298 | RangeDesc[Att].Asked = false; |
---|
| 299 | RangeDesc[Att].Known = false; |
---|
| 300 | CheckValue(Att, T); |
---|
| 301 | } |
---|
| 302 | |
---|
| 303 | |
---|
| 304 | |
---|
| 305 | /*************************************************************************/ |
---|
| 306 | /* */ |
---|
| 307 | /* Skip to the end of the line of input */ |
---|
| 308 | /* */ |
---|
| 309 | /*************************************************************************/ |
---|
| 310 | |
---|
| 311 | |
---|
| 312 | SkipLine(c) |
---|
| 313 | /* -------- */ |
---|
| 314 | char c; |
---|
| 315 | { |
---|
| 316 | while ( c != '\n' ) c = getchar(); |
---|
| 317 | } |
---|
| 318 | |
---|
| 319 | |
---|
| 320 | |
---|
| 321 | /*************************************************************************/ |
---|
| 322 | /* */ |
---|
| 323 | /* Clear the range description */ |
---|
| 324 | /* */ |
---|
| 325 | /*************************************************************************/ |
---|
| 326 | |
---|
| 327 | Clear() |
---|
| 328 | /* ----- */ |
---|
| 329 | { |
---|
| 330 | Attribute Att; |
---|
| 331 | |
---|
| 332 | ForEach(Att, 0, MaxAtt) |
---|
| 333 | { |
---|
| 334 | RangeDesc[Att].Known = false; |
---|
| 335 | } |
---|
| 336 | } |
---|