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