fable 3.1.34 → 3.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -461,6 +461,68 @@ suite
461
461
  Expect(parseFloat(tmpResult)).to.be.at.most(13.78);
462
462
 
463
463
 
464
+ return fDone();
465
+ }
466
+ );
467
+ test
468
+ (
469
+ 'Test map operation',
470
+ (fDone) =>
471
+ {
472
+ let testFable = new libFable();
473
+ let _Parser = testFable.instantiateServiceProviderIfNotExists('ExpressionParser');
474
+
475
+
476
+ let tmpManifest = testFable.newManyfest();
477
+ let tmpDataSourceObject = {};
478
+ tmpDataSourceObject.CitiesData = require('./data/Cities.json');
479
+ /* Records look like:
480
+ [
481
+ {
482
+ "city": "New York",
483
+ "growth_from_2000_to_2013": "4.8%",
484
+ "latitude": 40.7127837,
485
+ "longitude": -74.0059413,
486
+ "population": "8405837",
487
+ "rank": "1",
488
+ "state": "New York"
489
+ },
490
+ {
491
+ "city": "Los Angeles",
492
+ "growth_from_2000_to_2013": "4.8%",
493
+ "latitude": 34.0522342,
494
+ "longitude": -118.2436849,
495
+ "population": "3884307",
496
+ "rank": "2",
497
+ "state": "California"
498
+ },
499
+ */
500
+
501
+ tmpDataSourceObject.MapTest = {};
502
+ tmpDataSourceObject.MapTest.Values = [ 1, 2, 3, 4, 5 ];
503
+
504
+ let tmpDataDestinationObject = {};
505
+ let tmpParserResultsObject = {};
506
+
507
+ let tmpResult = _Parser.solve('SimpleMapResult = MAP VAR x FROM MapTest.Values : x + 100', tmpDataSourceObject, tmpParserResultsObject, tmpManifest, tmpDataDestinationObject);
508
+
509
+ // Should expect 101 -> 105
510
+ Expect(tmpDataDestinationObject.SimpleMapResult.length).to.equal(5);
511
+ Expect(tmpDataDestinationObject.SimpleMapResult[0]).to.equal("101");
512
+ Expect(tmpDataDestinationObject.SimpleMapResult[1]).to.equal("102");
513
+ Expect(tmpDataDestinationObject.SimpleMapResult[2]).to.equal("103");
514
+ Expect(tmpDataDestinationObject.SimpleMapResult[3]).to.equal("104");
515
+ Expect(tmpDataDestinationObject.SimpleMapResult[4]).to.equal("105");
516
+
517
+ let tmpComplexMapResult = _Parser.solve('ComplexMapResult = MAP VAR cityRecord FROM CitiesData VAR x FROM MapTest.Values : cityRecord.population + (x * 1000000000000000)', tmpDataSourceObject, tmpParserResultsObject, tmpManifest, tmpDataDestinationObject);
518
+
519
+ Expect(tmpDataDestinationObject.ComplexMapResult.length).to.equal(1000);
520
+ Expect(tmpDataDestinationObject.ComplexMapResult[0]).to.equal("1000000008405837");
521
+ Expect(tmpDataDestinationObject.ComplexMapResult[4]).to.equal("5000000001553165");
522
+ // We ran out of values 1-5 so now it's just population
523
+ Expect(tmpDataDestinationObject.ComplexMapResult[10]).to.equal("885400");
524
+ Expect(tmpDataDestinationObject.ComplexMapResult[400]).to.equal("81050");
525
+
464
526
  return fDone();
465
527
  }
466
528
  );
@@ -477,6 +539,13 @@ suite
477
539
  let tmpDataDestinationObject = {};
478
540
  let tmpParserResultsObject = {};
479
541
 
542
+ /* FIXME: This test is broken since `n` doesn't result in a valid postfix expression for the series generation.
543
+ let tmpPassthroughResult = _Parser.solve('IntegrationApproximationResult = SERIES FROM 13.2 TO 25 STEP 0.2 : n', tmpDataSourceObject, tmpParserResultsObject, tmpManifest, tmpDataDestinationObject);
544
+ Expect(tmpDataDestinationObject.IntegrationApproximationResult[0]).to.equal("13.2");
545
+ Expect(tmpDataDestinationObject.IntegrationApproximationResult[1]).to.equal("13.4");
546
+ Expect(tmpDataDestinationObject.IntegrationApproximationResult[59]).to.equal("25");
547
+ */
548
+
480
549
  // Approximate an integration of the function 1000 + (n / 2) from 13.2 and 25 every 0.2 values
481
550
  let tmpResult = _Parser.solve('IntegrationApproximationResult = SERIES FROM 13.2 TO 25 STEP 0.2 : 1000 + (n / 2)', tmpDataSourceObject, tmpParserResultsObject, tmpManifest, tmpDataDestinationObject);
482
551
  Expect(tmpDataDestinationObject.IntegrationApproximationResult[0]).to.equal("1006.6");
@@ -506,6 +575,69 @@ suite
506
575
  }
507
576
  );
508
577
  test
578
+ (
579
+ 'Test monte carlo...',
580
+ (fDone) =>
581
+ {
582
+ let testFable = new libFable();
583
+ let _Parser = testFable.instantiateServiceProviderIfNotExists('ExpressionParser');
584
+ let tmpManifest = testFable.newManyfest();
585
+
586
+ let tmpDataSourceObject = {};
587
+ let tmpDataDestinationObject = {};
588
+ let tmpParserResultsObject = {};
589
+
590
+ // Approximate an integration of the function 1000 + (n / 2) from 13.2 and 25 every 0.2 values
591
+ let tmpResult = _Parser.solve('MonteCarloResult = MONTECARLO SAMPLECOUNT 1000 VAR x PT x 50 PT x 100 : 10000000 + x', tmpDataSourceObject, tmpParserResultsObject, tmpManifest, tmpDataDestinationObject);
592
+
593
+ // Generate 1000 samples between 50 and 100, added to 10 million
594
+ Expect(tmpResult).to.exist;
595
+ Expect(tmpResult.Samples.length).to.equal(1000);
596
+
597
+ // Rosenbrock function test (experimenting with non-deterministic test cases)
598
+ /* Interesting values:
599
+
600
+ | Purpose | (x) | (y) | (z) | Notes |
601
+ | ----------------------------------------- | ----------------- | ----------------- | ----------------- | ------------------------------------------------------------------------------- |
602
+ | **Exploration (broad view)** | ([-3, 3]) | ([-1, 5]) | ([-1, 5]) | Shows how the function grows large and steep outside the valley. |
603
+ | **Focused optimization testing** | ([0, 2]) | ([0, 2]) | ([0, 2]) | Focuses on region around the minimum — ideal for Monte Carlo convergence plots. |
604
+ | **High-resolution contour visualization** | ([-1.5, 1.5]) | ([0, 2]) | ([0, 2]) | Best for plotting slices and seeing the curvature of the valley. |
605
+ | **Stress testing** | ([-2.048, 2.048]) | ([-2.048, 2.048]) | ([-2.048, 2.048]) | Tests the function's behavior over a wider range, useful for robustness checks. |
606
+ */
607
+ let tmpRosenbrockDataSourceObject = {};
608
+ let tmpRosenbrockDataDestinationObject = {};
609
+ let tmpRosenbrockParserResultsObject = {};
610
+ let tmpRosenbrockResult = _Parser.solve('RosenbrockResult = MONTECARLO SAMPLECOUNT 5000 VAR x PT x -3 PT x 3 VAR y PT y -1 PT y 5 VAR z PT z -1 PT z 5 : (1 - x)^2 + 100 * (y - x^2)^2 + (z - y)^2', tmpRosenbrockDataSourceObject, tmpRosenbrockParserResultsObject, tmpManifest, tmpRosenbrockDataDestinationObject);
611
+
612
+ Expect(tmpRosenbrockResult).to.exist;
613
+ Expect(tmpRosenbrockResult.Samples.length).to.equal(5000);
614
+
615
+ // Build a histogram of the results to see how many are near zero
616
+ let tmpHistogram = [];
617
+ for (let sampleIndex = 0; sampleIndex < tmpRosenbrockResult.Samples.length; sampleIndex++)
618
+ {
619
+ let tmpSample = tmpRosenbrockResult.Samples[sampleIndex];
620
+ let tmpValue = testFable.Math.roundPrecise(tmpSample, 0);
621
+ if (!tmpHistogram[tmpValue])
622
+ tmpHistogram[tmpValue] = 0;
623
+ tmpHistogram[tmpValue] = tmpHistogram[tmpValue] + 1;
624
+ // Log the output sample for visual inspection
625
+ testFable.log.info(`Rosenbrock Sample ${sampleIndex}: Value: ${tmpSample}, Rounded Value: ${tmpValue} --> Histogram Count: ${tmpHistogram[tmpValue]}`);
626
+ }
627
+ // Output the histogram for visual inspection
628
+ //testFable.ExpressionParser.Messaging.logMessage("Rosenbrock Histogram:");
629
+ let tmpHistogramKeys = Object.keys(tmpHistogram);
630
+ tmpHistogramKeys.sort((a, b) => parseFloat(a) - parseFloat(b));
631
+ for (let i = 0; i < tmpHistogramKeys.length; i++)
632
+ {
633
+ let key = tmpHistogramKeys[i];
634
+ testFable.log.info(`Value: ${key}, Count: ${tmpHistogram[key]}`);
635
+ }
636
+
637
+ return fDone();
638
+ }
639
+ );
640
+ test
509
641
  (
510
642
  'Complex Histogram Arithmatic',
511
643
  (fDone) =>
@@ -525,6 +525,45 @@ suite
525
525
  }
526
526
  );
527
527
  test
528
+ (
529
+ 'match returns an index into an array of values',
530
+ function()
531
+ {
532
+ testFable = new libFable();
533
+
534
+ let tmpState = [ '-1', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10' ];
535
+ let tmpResult = testFable.services.Utility.findIndexInternal('4.5', tmpState);
536
+ Expect(tmpResult).to.be.a('number');
537
+ Expect(tmpResult).to.equal(6);
538
+
539
+ tmpResult = testFable.services.Utility.findIndexInternal('11', tmpState);
540
+ Expect(tmpResult).to.be.a('number');
541
+ Expect(tmpResult).to.equal(-1);
542
+
543
+ tmpResult = testFable.services.Utility.findIndexInternal('4', tmpState);
544
+ Expect(tmpResult).to.be.a('number');
545
+ Expect(tmpResult).to.equal(5);
546
+
547
+ tmpResult = testFable.services.Utility.findIndexInternal('4.5', tmpState, '0');
548
+ Expect(tmpResult).to.be.a('number');
549
+ Expect(tmpResult).to.equal(-1);
550
+
551
+ tmpResult = testFable.services.Utility.findIndexInternal('4', tmpState, 0);
552
+ Expect(tmpResult).to.be.a('number');
553
+ Expect(tmpResult).to.equal(5);
554
+
555
+ tmpState = [ '10', '9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '-1' ];
556
+
557
+ tmpResult = testFable.services.Utility.findIndexInternal('4.5', tmpState, '-1');
558
+ Expect(tmpResult).to.be.a('number');
559
+ Expect(tmpResult).to.equal(6);
560
+
561
+ tmpResult = testFable.services.Utility.findIndexInternal('4', tmpState, -1);
562
+ Expect(tmpResult).to.be.a('number');
563
+ Expect(tmpResult).to.equal(6);
564
+ }
565
+ );
566
+ test
528
567
  (
529
568
  'createArrayFromAbsoluteValues works as expected',
530
569
  function(fDone)
@@ -544,4 +583,4 @@ suite
544
583
  }
545
584
  );
546
585
  }
547
- );
586
+ );