Changeset 17758
- Timestamp:
- 09/24/20 11:16:05 (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3073_IA_constraint_splitting/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/IntervalInterpreter.cs
r17757 r17758 312 312 return 0; 313 313 } 314 315 public static Interval EvaluateRecursive( 316 Instruction[] instructions, 317 IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals, 318 IDictionary<string, Interval> variableIntervals, IList<string> variables, 319 double minWidth, int maxDepth, ref int currIndex, ref int currDepth, 320 ISymbolicExpressionTree tree) { 321 Interval evaluate() { 322 var ic = 0; 323 IReadOnlyDictionary<string, Interval> readonlyRanges = 324 new ReadOnlyDictionary<string, Interval>(variableIntervals); 325 return Evaluate(instructions, ref ic, nodeIntervals, readonlyRanges); 314 } 315 316 public static Interval EvaluateRecursive( 317 Instruction[] instructions, 318 IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals, 319 IDictionary<string, Interval> variableIntervals, IList<string> variables, 320 double minWidth, int maxDepth, ref int currIndex, ref int currDepth, 321 ISymbolicExpressionTree tree) { 322 Interval evaluate() { 323 var ic = 0; 324 IReadOnlyDictionary<string, Interval> readonlyRanges = 325 new ReadOnlyDictionary<string, Interval>(variableIntervals); 326 return Evaluate(instructions, ref ic, nodeIntervals, readonlyRanges); 327 } 328 329 Interval recurse(ref int idx, ref int depth) { 330 return EvaluateRecursive(instructions, nodeIntervals, variableIntervals, variables, minWidth, maxDepth, ref idx, 331 ref depth, tree); 332 } 333 334 335 var v = variables[currIndex]; 336 var x = variableIntervals[v]; 337 if (x.Width < minWidth || currDepth == maxDepth || !MultipleTimes(tree, v)) { 338 if (currIndex + 1 < variables.Count) { 339 currDepth = 0; 340 currIndex++; 341 var z = recurse(ref currIndex, ref currDepth); 342 currIndex--; 343 return z; 326 344 } 327 345 328 Interval recurse(ref int idx, ref int depth) { 329 return EvaluateRecursive(instructions, nodeIntervals, variableIntervals, variables, minWidth, maxDepth, ref idx, 330 ref depth, tree); 331 } 332 333 334 var v = variables[currIndex]; 335 var x = variableIntervals[v]; 336 if (x.Width < minWidth || currDepth == maxDepth || !MultipleTimes(tree, v)) { 337 if (currIndex + 1 < variables.Count) { 338 currDepth = 0; 339 currIndex++; 340 var z = recurse(ref currIndex, ref currDepth); 341 currIndex--; 342 return z; 343 } 344 345 return evaluate(); 346 } 347 348 var t = x.Split(); 349 var xa = t.Item1; 350 var xb = t.Item2; 351 var d = currDepth; 352 currDepth = d + 1; 353 variableIntervals[v] = xa; 354 var ya = recurse(ref currIndex, ref currDepth); 355 currDepth = d + 1; 356 variableIntervals[v] = xb; 357 var yb = recurse(ref currIndex, ref currDepth); 358 variableIntervals[v] = x; // restore interval 359 return ya | yb; 360 } 361 362 public static Interval Evaluate( 363 Instruction[] instructions, ref int instructionCounter, 364 IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null, 365 IReadOnlyDictionary<string, Interval> variableIntervals = null) { 366 var currentInstr = instructions[instructionCounter]; 367 //Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side 368 //Update instructionCounter, whenever Evaluate is called 369 instructionCounter++; 370 Interval result = null; 371 372 switch (currentInstr.opCode) { 373 //Variables, Constants, ... 374 case OpCodes.Variable: { 375 var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode; 376 var weightInterval = new Interval(variableTreeNode.Weight, variableTreeNode.Weight); 377 //var variableInterval = (Interval)currentInstr.data; 378 379 Interval variableInterval; 380 if (variableIntervals != null && variableIntervals.ContainsKey(variableTreeNode.VariableName)) 381 variableInterval = variableIntervals[variableTreeNode.VariableName]; 382 else 383 variableInterval = (Interval)currentInstr.data; 384 385 result = Interval.Multiply(variableInterval, weightInterval); 386 break; 387 } 388 case OpCodes.Constant: { 389 var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode; 390 result = new Interval(constTreeNode.Value, constTreeNode.Value); 391 break; 392 } 393 //Elementary arithmetic rules 394 case OpCodes.Add: { 395 //result = Evaluate(instructions, ref instructionCounter, nodeIntervals); 396 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 397 for (var i = 1; i < currentInstr.nArguments; i++) { 398 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 399 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 400 result = Interval.Add(result, argumentInterval); 401 } 402 403 break; 404 } 405 case OpCodes.Sub: { 406 //result = Evaluate(instructions, ref instructionCounter, nodeIntervals); 407 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 408 if (currentInstr.nArguments == 1) 409 result = Interval.Multiply(new Interval(-1, -1), result); 410 411 for (var i = 1; i < currentInstr.nArguments; i++) { 412 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 413 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 414 result = Interval.Subtract(result, argumentInterval); 415 } 416 417 break; 418 } 419 case OpCodes.Mul: { 420 //result = Evaluate(instructions, ref instructionCounter, nodeIntervals); 421 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 422 for (var i = 1; i < currentInstr.nArguments; i++) { 423 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 424 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 425 result = Interval.Multiply(result, argumentInterval); 426 } 427 428 break; 429 } 430 case OpCodes.Div: { 431 //result = Evaluate(instructions, ref instructionCounter, nodeIntervals); 432 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 433 if (currentInstr.nArguments == 1) 434 result = Interval.Divide(new Interval(1, 1), result); 435 436 for (var i = 1; i < currentInstr.nArguments; i++) { 437 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 438 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 439 result = Interval.Divide(result, argumentInterval); 440 } 441 442 break; 443 } 444 //Trigonometric functions 445 case OpCodes.Sin: { 346 return evaluate(); 347 } 348 349 var t = x.Split(); 350 var xa = t.Item1; 351 var xb = t.Item2; 352 var d = currDepth; 353 currDepth = d + 1; 354 variableIntervals[v] = xa; 355 var ya = recurse(ref currIndex, ref currDepth); 356 currDepth = d + 1; 357 variableIntervals[v] = xb; 358 var yb = recurse(ref currIndex, ref currDepth); 359 variableIntervals[v] = x; // restore interval 360 return ya | yb; 361 } 362 363 public static Interval Evaluate( 364 Instruction[] instructions, ref int instructionCounter, 365 IDictionary<ISymbolicExpressionTreeNode, Interval> nodeIntervals = null, 366 IReadOnlyDictionary<string, Interval> variableIntervals = null) { 367 var currentInstr = instructions[instructionCounter]; 368 //Use ref parameter, because the tree will be iterated through recursively from the left-side branch to the right side 369 //Update instructionCounter, whenever Evaluate is called 370 instructionCounter++; 371 Interval result = null; 372 373 switch (currentInstr.opCode) { 374 //Variables, Constants, ... 375 case OpCodes.Variable: { 376 var variableTreeNode = (VariableTreeNode)currentInstr.dynamicNode; 377 var weightInterval = new Interval(variableTreeNode.Weight, variableTreeNode.Weight); 378 //var variableInterval = (Interval)currentInstr.data; 379 380 Interval variableInterval; 381 if (variableIntervals != null && variableIntervals.ContainsKey(variableTreeNode.VariableName)) 382 variableInterval = variableIntervals[variableTreeNode.VariableName]; 383 else 384 variableInterval = (Interval)currentInstr.data; 385 386 result = Interval.Multiply(variableInterval, weightInterval); 387 break; 388 } 389 case OpCodes.Constant: { 390 var constTreeNode = (ConstantTreeNode)currentInstr.dynamicNode; 391 result = new Interval(constTreeNode.Value, constTreeNode.Value); 392 break; 393 } 394 //Elementary arithmetic rules 395 case OpCodes.Add: { 396 //result = Evaluate(instructions, ref instructionCounter, nodeIntervals); 397 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 398 for (var i = 1; i < currentInstr.nArguments; i++) { 446 399 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 447 400 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 448 result = Interval.Sine(argumentInterval); 449 break; 401 result = Interval.Add(result, argumentInterval); 450 402 } 451 case OpCodes.Cos: { 403 404 break; 405 } 406 case OpCodes.Sub: { 407 //result = Evaluate(instructions, ref instructionCounter, nodeIntervals); 408 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 409 if (currentInstr.nArguments == 1) 410 result = Interval.Multiply(new Interval(-1, -1), result); 411 412 for (var i = 1; i < currentInstr.nArguments; i++) { 452 413 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 453 414 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 454 result = Interval.Cosine(argumentInterval); 455 break; 415 result = Interval.Subtract(result, argumentInterval); 456 416 } 457 case OpCodes.Tan: { 417 418 break; 419 } 420 case OpCodes.Mul: { 421 //result = Evaluate(instructions, ref instructionCounter, nodeIntervals); 422 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 423 for (var i = 1; i < currentInstr.nArguments; i++) { 424 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 425 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 426 result = Interval.Multiply(result, argumentInterval); 427 } 428 429 break; 430 } 431 case OpCodes.Div: { 432 //result = Evaluate(instructions, ref instructionCounter, nodeIntervals); 433 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 434 if (currentInstr.nArguments == 1) 435 result = Interval.Divide(new Interval(1, 1), result); 436 437 for (var i = 1; i < currentInstr.nArguments; i++) { 458 438 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 459 439 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 460 result = Interval.Tangens(argumentInterval); 461 break; 440 result = Interval.Divide(result, argumentInterval); 462 441 } 463 case OpCodes.Tanh: { 442 443 break; 444 } 445 //Trigonometric functions 446 case OpCodes.Sin: { 447 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 448 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 449 result = Interval.Sine(argumentInterval); 450 break; 451 } 452 case OpCodes.Cos: { 453 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 454 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 455 result = Interval.Cosine(argumentInterval); 456 break; 457 } 458 case OpCodes.Tan: { 459 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 460 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 461 result = Interval.Tangens(argumentInterval); 462 break; 463 } 464 case OpCodes.Tanh: { 465 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 466 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 467 result = Interval.HyperbolicTangent(argumentInterval); 468 break; 469 } 470 //Exponential functions 471 case OpCodes.Log: { 472 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 473 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 474 result = Interval.Logarithm(argumentInterval); 475 break; 476 } 477 case OpCodes.Exp: { 478 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 479 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 480 result = Interval.Exponential(argumentInterval); 481 break; 482 } 483 case OpCodes.Square: { 484 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 485 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 486 result = Interval.Square(argumentInterval); 487 break; 488 } 489 case OpCodes.SquareRoot: { 490 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 491 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 492 result = Interval.SquareRoot(argumentInterval); 493 break; 494 } 495 case OpCodes.Cube: { 496 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 497 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 498 result = Interval.Cube(argumentInterval); 499 break; 500 } 501 case OpCodes.CubeRoot: { 502 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 503 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 504 result = Interval.CubicRoot(argumentInterval); 505 break; 506 } 507 case OpCodes.Absolute: { 508 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 509 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 510 result = Interval.Absolute(argumentInterval); 511 break; 512 } 513 case OpCodes.AnalyticQuotient: { 514 //result = Evaluate(instructions, ref instructionCounter, nodeIntervals); 515 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 516 for (var i = 1; i < currentInstr.nArguments; i++) { 464 517 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 465 518 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 466 result = Interval.HyperbolicTangent(argumentInterval); 467 break; 519 result = Interval.AnalyticalQuotient(result, argumentInterval); 468 520 } 469 //Exponential functions 470 case OpCodes.Log: { 471 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 472 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 473 result = Interval.Logarithm(argumentInterval); 474 break; 475 } 476 case OpCodes.Exp: { 477 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 478 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 479 result = Interval.Exponential(argumentInterval); 480 break; 481 } 482 case OpCodes.Square: { 483 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 484 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 485 result = Interval.Square(argumentInterval); 486 break; 487 } 488 case OpCodes.SquareRoot: { 489 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 490 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 491 result = Interval.SquareRoot(argumentInterval); 492 break; 493 } 494 case OpCodes.Cube: { 495 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 496 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 497 result = Interval.Cube(argumentInterval); 498 break; 499 } 500 case OpCodes.CubeRoot: { 501 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 502 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 503 result = Interval.CubicRoot(argumentInterval); 504 break; 505 } 506 case OpCodes.Absolute: { 507 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 508 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 509 result = Interval.Absolute(argumentInterval); 510 break; 511 } 512 case OpCodes.AnalyticQuotient: { 513 //result = Evaluate(instructions, ref instructionCounter, nodeIntervals); 514 result = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 515 for (var i = 1; i < currentInstr.nArguments; i++) { 516 //var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals); 517 var argumentInterval = Evaluate(instructions, ref instructionCounter, nodeIntervals, variableIntervals); 518 result = Interval.AnalyticalQuotient(result, argumentInterval); 519 } 520 521 break; 522 } 523 default: 524 throw new NotSupportedException($"The tree contains the unknown symbol {currentInstr.dynamicNode.Symbol}"); 525 } 526 527 if (!(nodeIntervals == null || nodeIntervals.ContainsKey(currentInstr.dynamicNode))) 528 nodeIntervals.Add(currentInstr.dynamicNode, result); 529 530 return result; 531 } 532 533 private static bool MultipleTimes(ISymbolicExpressionTree tree, string variable) { 534 var varlist = tree.IterateNodesPrefix().OfType<VariableTreeNode>().GroupBy(x => x.VariableName); 535 var group = varlist.Select(x => x.Key == variable).Count(); 536 537 return group > 1; 538 } 539 540 private static bool ContainsVariableMultipleTimes(ISymbolicExpressionTree tree) { 541 var varlist = tree.IterateNodesPrefix().OfType<VariableTreeNode>().GroupBy(x => x.VariableName); 542 return varlist.Any(group => group.Count() > 1); 543 } 544 545 546 public static bool IsCompatible(ISymbolicExpressionTree tree) { 547 var containsUnknownSymbols = ( 548 from n in tree.Root.GetSubtree(0).IterateNodesPrefix() 549 where 550 !(n.Symbol is Variable) && 551 !(n.Symbol is Constant) && 552 !(n.Symbol is StartSymbol) && 553 !(n.Symbol is Addition) && 554 !(n.Symbol is Subtraction) && 555 !(n.Symbol is Multiplication) && 556 !(n.Symbol is Division) && 557 !(n.Symbol is Sine) && 558 !(n.Symbol is Cosine) && 559 !(n.Symbol is Tangent) && 560 !(n.Symbol is HyperbolicTangent) && 561 !(n.Symbol is Logarithm) && 562 !(n.Symbol is Exponential) && 563 !(n.Symbol is Square) && 564 !(n.Symbol is SquareRoot) && 565 !(n.Symbol is Cube) && 566 !(n.Symbol is CubeRoot) && 567 !(n.Symbol is Absolute) && 568 !(n.Symbol is AnalyticQuotient) 569 select n).Any(); 570 return !containsUnknownSymbols; 571 } 521 522 break; 523 } 524 default: 525 throw new NotSupportedException($"The tree contains the unknown symbol {currentInstr.dynamicNode.Symbol}"); 526 } 527 528 if (!(nodeIntervals == null || nodeIntervals.ContainsKey(currentInstr.dynamicNode))) 529 nodeIntervals.Add(currentInstr.dynamicNode, result); 530 531 return result; 532 } 533 534 private static bool MultipleTimes(ISymbolicExpressionTree tree, string variable) { 535 var varlist = tree.IterateNodesPrefix().OfType<VariableTreeNode>().GroupBy(x => x.VariableName); 536 var group = varlist.Select(x => x.Key == variable).Count(); 537 538 return group > 1; 539 } 540 541 private static bool ContainsVariableMultipleTimes(ISymbolicExpressionTree tree) { 542 var varlist = tree.IterateNodesPrefix().OfType<VariableTreeNode>().GroupBy(x => x.VariableName); 543 return varlist.Any(group => group.Count() > 1); 544 } 545 546 547 public static bool IsCompatible(ISymbolicExpressionTree tree) { 548 var containsUnknownSymbols = ( 549 from n in tree.Root.GetSubtree(0).IterateNodesPrefix() 550 where 551 !(n.Symbol is Variable) && 552 !(n.Symbol is Constant) && 553 !(n.Symbol is StartSymbol) && 554 !(n.Symbol is Addition) && 555 !(n.Symbol is Subtraction) && 556 !(n.Symbol is Multiplication) && 557 !(n.Symbol is Division) && 558 !(n.Symbol is Sine) && 559 !(n.Symbol is Cosine) && 560 !(n.Symbol is Tangent) && 561 !(n.Symbol is HyperbolicTangent) && 562 !(n.Symbol is Logarithm) && 563 !(n.Symbol is Exponential) && 564 !(n.Symbol is Square) && 565 !(n.Symbol is SquareRoot) && 566 !(n.Symbol is Cube) && 567 !(n.Symbol is CubeRoot) && 568 !(n.Symbol is Absolute) && 569 !(n.Symbol is AnalyticQuotient) 570 select n).Any(); 571 return !containsUnknownSymbols; 572 572 } 573 573 } 574 }
Note: See TracChangeset
for help on using the changeset viewer.