pub fn create_continual_task(
task_id: String,
task_type: TaskType,
data: Array2<f64>,
labels: Array1<usize>,
train_ratio: f64,
) -> ContinualTaskExpand description
Helper function to create a simple continual task
Examples found in repository?
examples/quantum_continual_learning.rs (lines 612-618)
568fn generate_diverse_tasks(
569 num_tasks: usize,
570 samples_per_task: usize,
571 feature_dim: usize,
572) -> Vec<ContinualTask> {
573 let mut tasks = Vec::new();
574
575 for i in 0..num_tasks {
576 let task_type = match i % 3 {
577 0 => "classification",
578 1 => "pattern_recognition",
579 _ => "feature_detection",
580 };
581
582 // Generate task-specific data with different distributions
583 let data = Array2::from_shape_fn((samples_per_task, feature_dim), |(row, col)| {
584 match i % 3 {
585 0 => {
586 // Gaussian-like distribution
587 let center = i as f64 * 0.2;
588 center + 0.2 * (fastrand::f64() - 0.5)
589 }
590 1 => {
591 // Sinusoidal pattern
592 let freq = (i + 1) as f64;
593 0.5 + 0.3 * (freq * row as f64 * 0.1 + col as f64 * 0.2).sin()
594 }
595 _ => {
596 // Random with task-specific bias
597 let bias = i as f64 * 0.1;
598 bias + fastrand::f64() * 0.6
599 }
600 }
601 });
602
603 let labels = Array1::from_shape_fn(samples_per_task, |row| {
604 let features_sum = data.row(row).sum();
605 if features_sum > feature_dim as f64 * 0.5 {
606 1
607 } else {
608 0
609 }
610 });
611
612 let task = create_continual_task(
613 format!("{}_{}", task_type, i),
614 TaskType::Classification { num_classes: 2 },
615 data,
616 labels,
617 0.8,
618 );
619
620 tasks.push(task);
621 }
622
623 tasks
624}
625
626/// Generate related tasks for transfer learning
627fn generate_related_tasks(
628 num_tasks: usize,
629 samples_per_task: usize,
630 feature_dim: usize,
631) -> Vec<ContinualTask> {
632 let mut tasks = Vec::new();
633 let base_pattern = Array1::from_shape_fn(feature_dim, |i| (i as f64 * 0.3).sin());
634
635 for i in 0..num_tasks {
636 // Each task is a variation of the base pattern
637 let variation_strength = 0.1 + i as f64 * 0.1;
638
639 let data = Array2::from_shape_fn((samples_per_task, feature_dim), |(row, col)| {
640 let base_value = base_pattern[col];
641 let variation = variation_strength * (row as f64 * 0.05 + col as f64 * 0.1).cos();
642 let noise = 0.05 * (fastrand::f64() - 0.5);
643 (base_value + variation + noise).max(0.0).min(1.0)
644 });
645
646 let labels = Array1::from_shape_fn(samples_per_task, |row| {
647 let correlation = data
648 .row(row)
649 .iter()
650 .zip(base_pattern.iter())
651 .map(|(&x, &y)| x * y)
652 .sum::<f64>();
653 if correlation > 0.5 {
654 1
655 } else {
656 0
657 }
658 });
659
660 let task = create_continual_task(
661 format!("related_task_{}", i),
662 TaskType::Classification { num_classes: 2 },
663 data,
664 labels,
665 0.8,
666 );
667
668 tasks.push(task);
669 }
670
671 tasks
672}
673
674/// Generate tasks with varying complexity
675fn generate_varying_complexity_tasks(
676 num_tasks: usize,
677 samples_per_task: usize,
678 feature_dim: usize,
679) -> Vec<ContinualTask> {
680 let mut tasks = Vec::new();
681
682 for i in 0..num_tasks {
683 let complexity = (i + 1) as f64; // Increasing complexity
684
685 let data = Array2::from_shape_fn((samples_per_task, feature_dim), |(row, col)| {
686 // More complex decision boundaries for later tasks
687 let x = row as f64 / samples_per_task as f64;
688 let y = col as f64 / feature_dim as f64;
689
690 let value = match i {
691 0 => {
692 if x > 0.5 {
693 1.0
694 } else {
695 0.0
696 }
697 } // Simple linear
698 1 => {
699 if x * x + y * y > 0.25 {
700 1.0
701 } else {
702 0.0
703 }
704 } // Circular
705 2 => {
706 if (x * 4.0).sin() * (y * 4.0).cos() > 0.0 {
707 1.0
708 } else {
709 0.0
710 }
711 } // Sinusoidal
712 _ => {
713 // Very complex pattern
714 let pattern = (x * 8.0).sin() * (y * 8.0).cos() + (x * y * 16.0).sin();
715 if pattern > 0.0 {
716 1.0
717 } else {
718 0.0
719 }
720 }
721 };
722
723 value + 0.1 * (fastrand::f64() - 0.5) // Add noise
724 });
725
726 let labels = Array1::from_shape_fn(samples_per_task, |row| {
727 // Complex labeling based on multiple features
728 let features = data.row(row);
729 let decision_value = features
730 .iter()
731 .enumerate()
732 .map(|(j, &x)| x * (1.0 + j as f64 * complexity * 0.1))
733 .sum::<f64>();
734
735 if decision_value > feature_dim as f64 * 0.5 {
736 1
737 } else {
738 0
739 }
740 });
741
742 let task = create_continual_task(
743 format!("complex_task_{}", i),
744 TaskType::Classification { num_classes: 2 },
745 data,
746 labels,
747 0.8,
748 );
749
750 tasks.push(task);
751 }
752
753 tasks
754}
755
756/// Generate challenging task sequence
757fn generate_challenging_sequence(
758 num_tasks: usize,
759 samples_per_task: usize,
760 feature_dim: usize,
761) -> Vec<ContinualTask> {
762 let mut tasks = Vec::new();
763
764 for i in 0..num_tasks {
765 // Alternating between different types of challenges
766 let challenge_type = i % 4;
767
768 let data = Array2::from_shape_fn((samples_per_task, feature_dim), |(row, col)| {
769 match challenge_type {
770 0 => {
771 // High-frequency patterns
772 let freq = 10.0 + i as f64 * 2.0;
773 0.5 + 0.4 * (freq * row as f64 * 0.01).sin()
774 }
775 1 => {
776 // Overlapping distributions
777 let center1 = 0.3 + i as f64 * 0.05;
778 let center2 = 0.7 - i as f64 * 0.05;
779 if row % 2 == 0 {
780 center1 + 0.15 * (fastrand::f64() - 0.5)
781 } else {
782 center2 + 0.15 * (fastrand::f64() - 0.5)
783 }
784 }
785 2 => {
786 // Non-linear patterns
787 let x = row as f64 / samples_per_task as f64;
788 let y = col as f64 / feature_dim as f64;
789 let pattern = (x * x - y * y + i as f64 * 0.1).tanh();
790 0.5 + 0.3 * pattern
791 }
792 _ => {
793 // Sparse patterns
794 if fastrand::f64() < 0.2 {
795 0.8 + 0.2 * fastrand::f64()
796 } else {
797 0.1 * fastrand::f64()
798 }
799 }
800 }
801 });
802
803 let labels = Array1::from_shape_fn(samples_per_task, |row| {
804 let features = data.row(row);
805 match challenge_type {
806 0 => {
807 if features.sum() > feature_dim as f64 * 0.5 {
808 1
809 } else {
810 0
811 }
812 }
813 1 => {
814 if features[0] > 0.5 {
815 1
816 } else {
817 0
818 }
819 }
820 2 => {
821 if features
822 .iter()
823 .enumerate()
824 .map(|(j, &x)| x * (j as f64 + 1.0))
825 .sum::<f64>()
826 > 2.0
827 {
828 1
829 } else {
830 0
831 }
832 }
833 _ => {
834 if features.iter().filter(|&&x| x > 0.5).count() > feature_dim / 2 {
835 1
836 } else {
837 0
838 }
839 }
840 }
841 });
842
843 let task = create_continual_task(
844 format!("challenge_{}", i),
845 TaskType::Classification { num_classes: 2 },
846 data,
847 labels,
848 0.8,
849 );
850
851 tasks.push(task);
852 }
853
854 tasks
855}
856
857/// Generate tasks with increasing difficulty
858fn generate_increasing_difficulty_tasks(
859 num_tasks: usize,
860 samples_per_task: usize,
861 feature_dim: usize,
862) -> Vec<ContinualTask> {
863 let mut tasks = Vec::new();
864
865 for i in 0..num_tasks {
866 let difficulty = (i + 1) as f64;
867 let noise_level = 0.05 + difficulty * 0.02;
868 let pattern_complexity = 1.0 + difficulty * 0.5;
869
870 let data = Array2::from_shape_fn((samples_per_task, feature_dim), |(row, col)| {
871 let x = row as f64 / samples_per_task as f64;
872 let y = col as f64 / feature_dim as f64;
873
874 // Increasingly complex patterns
875 let base_pattern = (x * pattern_complexity * std::f64::consts::PI).sin()
876 * (y * pattern_complexity * std::f64::consts::PI).cos();
877
878 let pattern_value = 0.5 + 0.3 * base_pattern;
879 let noise = noise_level * (fastrand::f64() - 0.5);
880
881 (pattern_value + noise).max(0.0).min(1.0)
882 });
883
884 let labels = Array1::from_shape_fn(samples_per_task, |row| {
885 let features = data.row(row);
886
887 // Increasingly complex decision boundaries
888 let decision_value = features
889 .iter()
890 .enumerate()
891 .map(|(j, &x)| {
892 let weight = 1.0 + (j as f64 * difficulty * 0.1).sin();
893 x * weight
894 })
895 .sum::<f64>();
896
897 let threshold = feature_dim as f64 * 0.5 * (1.0 + difficulty * 0.1);
898 if decision_value > threshold {
899 1
900 } else {
901 0
902 }
903 });
904
905 let task = create_continual_task(
906 format!("difficulty_{}", i + 1),
907 TaskType::Classification { num_classes: 2 },
908 data,
909 labels,
910 0.8,
911 );
912
913 tasks.push(task);
914 }
915
916 tasks
917}