superquantx 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl
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.
- superquantx/__init__.py +24 -12
- superquantx/algorithms/__init__.py +1 -1
- superquantx/algorithms/base_algorithm.py +36 -36
- superquantx/algorithms/hybrid_classifier.py +22 -22
- superquantx/algorithms/qaoa.py +29 -28
- superquantx/algorithms/quantum_agents.py +57 -56
- superquantx/algorithms/quantum_kmeans.py +17 -17
- superquantx/algorithms/quantum_nn.py +18 -18
- superquantx/algorithms/quantum_pca.py +26 -26
- superquantx/algorithms/quantum_svm.py +26 -25
- superquantx/algorithms/vqe.py +40 -39
- superquantx/algorithms.py +56 -55
- superquantx/backends/__init__.py +12 -12
- superquantx/backends/base_backend.py +25 -24
- superquantx/backends/braket_backend.py +21 -21
- superquantx/backends/cirq_backend.py +26 -26
- superquantx/backends/ocean_backend.py +38 -38
- superquantx/backends/pennylane_backend.py +12 -11
- superquantx/backends/qiskit_backend.py +12 -12
- superquantx/backends/simulator_backend.py +31 -17
- superquantx/backends/tket_backend.py +23 -23
- superquantx/circuits.py +25 -25
- superquantx/cli/commands.py +6 -7
- superquantx/cli/main.py +5 -6
- superquantx/client.py +42 -42
- superquantx/config.py +14 -14
- superquantx/datasets/__init__.py +58 -0
- superquantx/datasets/molecular.py +307 -0
- superquantx/datasets/preprocessing.py +279 -0
- superquantx/datasets/quantum_datasets.py +277 -0
- superquantx/datasets/synthetic.py +300 -0
- superquantx/exceptions.py +29 -29
- superquantx/gates.py +26 -26
- superquantx/logging_config.py +29 -29
- superquantx/measurements.py +53 -54
- superquantx/ml.py +51 -52
- superquantx/noise.py +49 -49
- superquantx/utils/benchmarking.py +41 -36
- superquantx/utils/classical_utils.py +32 -32
- superquantx/utils/feature_mapping.py +40 -35
- superquantx/utils/optimization.py +28 -26
- superquantx/utils/quantum_utils.py +47 -48
- superquantx/utils/visualization.py +49 -49
- superquantx/version.py +3 -3
- {superquantx-0.1.0.dist-info → superquantx-0.1.1.dist-info}/METADATA +18 -16
- superquantx-0.1.1.dist-info/RECORD +51 -0
- superquantx-0.1.1.dist-info/licenses/LICENSE +180 -0
- superquantx-0.1.0.dist-info/RECORD +0 -46
- superquantx-0.1.0.dist-info/licenses/LICENSE +0 -21
- {superquantx-0.1.0.dist-info → superquantx-0.1.1.dist-info}/WHEEL +0 -0
- {superquantx-0.1.0.dist-info → superquantx-0.1.1.dist-info}/entry_points.txt +0 -0
@@ -19,7 +19,8 @@ without human intervention.
|
|
19
19
|
import logging
|
20
20
|
import time
|
21
21
|
from abc import ABC, abstractmethod
|
22
|
-
from
|
22
|
+
from collections.abc import Callable
|
23
|
+
from typing import Any
|
23
24
|
|
24
25
|
import numpy as np
|
25
26
|
from sklearn.metrics import accuracy_score
|
@@ -36,11 +37,11 @@ logger = logging.getLogger(__name__)
|
|
36
37
|
|
37
38
|
class QuantumAgent(BaseQuantumAlgorithm, ABC):
|
38
39
|
"""Base class for quantum agents.
|
39
|
-
|
40
|
+
|
40
41
|
Quantum agents are specialized combinations of quantum algorithms
|
41
42
|
designed for specific problem domains. They provide high-level
|
42
43
|
interfaces for complex quantum machine learning workflows.
|
43
|
-
|
44
|
+
|
44
45
|
Args:
|
45
46
|
backend: Quantum backend for circuit execution
|
46
47
|
agent_config: Configuration dictionary for the agent
|
@@ -51,8 +52,8 @@ class QuantumAgent(BaseQuantumAlgorithm, ABC):
|
|
51
52
|
|
52
53
|
def __init__(
|
53
54
|
self,
|
54
|
-
backend:
|
55
|
-
agent_config:
|
55
|
+
backend: str | Any,
|
56
|
+
agent_config: dict[str, Any] | None = None,
|
56
57
|
shots: int = 1024,
|
57
58
|
**kwargs
|
58
59
|
) -> None:
|
@@ -75,18 +76,18 @@ class QuantumAgent(BaseQuantumAlgorithm, ABC):
|
|
75
76
|
@abstractmethod
|
76
77
|
def solve(self, problem_instance: Any, **kwargs) -> QuantumResult:
|
77
78
|
"""Solve a problem using the quantum agent.
|
78
|
-
|
79
|
+
|
79
80
|
Args:
|
80
81
|
problem_instance: Problem data/specification
|
81
82
|
**kwargs: Additional solving parameters
|
82
|
-
|
83
|
+
|
83
84
|
Returns:
|
84
85
|
Solution result
|
85
86
|
|
86
87
|
"""
|
87
88
|
pass
|
88
89
|
|
89
|
-
def get_agent_info(self) ->
|
90
|
+
def get_agent_info(self) -> dict[str, Any]:
|
90
91
|
"""Get information about the agent and its algorithms."""
|
91
92
|
return {
|
92
93
|
'agent_type': self.__class__.__name__,
|
@@ -98,11 +99,11 @@ class QuantumAgent(BaseQuantumAlgorithm, ABC):
|
|
98
99
|
|
99
100
|
class QuantumPortfolioAgent(QuantumAgent):
|
100
101
|
"""Quantum agent for portfolio optimization.
|
101
|
-
|
102
|
+
|
102
103
|
This agent combines QAOA and VQE algorithms to solve portfolio
|
103
104
|
optimization problems including mean-variance optimization,
|
104
105
|
risk parity, and constrained optimization.
|
105
|
-
|
106
|
+
|
106
107
|
Args:
|
107
108
|
backend: Quantum backend
|
108
109
|
risk_model: Risk model to use ('mean_variance', 'black_litterman', 'factor')
|
@@ -110,7 +111,7 @@ class QuantumPortfolioAgent(QuantumAgent):
|
|
110
111
|
constraints: List of constraint specifications
|
111
112
|
rebalancing_frequency: How often to rebalance
|
112
113
|
**kwargs: Additional parameters
|
113
|
-
|
114
|
+
|
114
115
|
Example:
|
115
116
|
>>> agent = QuantumPortfolioAgent(
|
116
117
|
... backend='pennylane',
|
@@ -124,10 +125,10 @@ class QuantumPortfolioAgent(QuantumAgent):
|
|
124
125
|
|
125
126
|
def __init__(
|
126
127
|
self,
|
127
|
-
backend:
|
128
|
+
backend: str | Any,
|
128
129
|
risk_model: str = 'mean_variance',
|
129
130
|
optimization_objective: str = 'sharpe',
|
130
|
-
constraints:
|
131
|
+
constraints: list[dict] | None = None,
|
131
132
|
rebalancing_frequency: str = 'monthly',
|
132
133
|
**kwargs
|
133
134
|
) -> None:
|
@@ -191,7 +192,7 @@ class QuantumPortfolioAgent(QuantumAgent):
|
|
191
192
|
|
192
193
|
return H
|
193
194
|
|
194
|
-
def _encode_constraints(self, constraints:
|
195
|
+
def _encode_constraints(self, constraints: list[dict], n_assets: int) -> list[Callable]:
|
195
196
|
"""Encode portfolio constraints as quantum operators."""
|
196
197
|
quantum_constraints = []
|
197
198
|
|
@@ -212,30 +213,30 @@ class QuantumPortfolioAgent(QuantumAgent):
|
|
212
213
|
|
213
214
|
elif constraint_type == 'max_weight':
|
214
215
|
# Maximum weight constraint
|
215
|
-
|
216
|
-
def max_weight_constraint(weights):
|
216
|
+
max_weight_value = constraint.get('value', 0.3)
|
217
|
+
def max_weight_constraint(weights, max_weight=max_weight_value):
|
217
218
|
return np.sum(np.maximum(0, weights - max_weight) ** 2)
|
218
219
|
quantum_constraints.append(max_weight_constraint)
|
219
220
|
|
220
221
|
elif constraint_type == 'sector_limit':
|
221
222
|
# Sector exposure limit
|
222
|
-
|
223
|
-
|
224
|
-
def sector_constraint(weights):
|
223
|
+
sector_assets_list = constraint.get('assets', [])
|
224
|
+
max_exposure_value = constraint.get('value', 0.5)
|
225
|
+
def sector_constraint(weights, sector_assets=sector_assets_list, max_exposure=max_exposure_value):
|
225
226
|
sector_exposure = np.sum(weights[sector_assets])
|
226
227
|
return np.maximum(0, sector_exposure - max_exposure) ** 2
|
227
228
|
quantum_constraints.append(sector_constraint)
|
228
229
|
|
229
230
|
return quantum_constraints
|
230
231
|
|
231
|
-
def fit(self, X: np.ndarray, y:
|
232
|
+
def fit(self, X: np.ndarray, y: np.ndarray | None = None, **kwargs) -> 'QuantumPortfolioAgent':
|
232
233
|
"""Fit the portfolio agent to historical data.
|
233
|
-
|
234
|
+
|
234
235
|
Args:
|
235
236
|
X: Historical returns data (samples x assets)
|
236
237
|
y: Not used
|
237
238
|
**kwargs: Additional parameters
|
238
|
-
|
239
|
+
|
239
240
|
Returns:
|
240
241
|
Self
|
241
242
|
|
@@ -275,11 +276,11 @@ class QuantumPortfolioAgent(QuantumAgent):
|
|
275
276
|
|
276
277
|
def solve(self, problem_instance: np.ndarray, **kwargs) -> QuantumResult:
|
277
278
|
"""Solve portfolio optimization problem.
|
278
|
-
|
279
|
+
|
279
280
|
Args:
|
280
281
|
problem_instance: Returns data or problem specification
|
281
282
|
**kwargs: Solving parameters
|
282
|
-
|
283
|
+
|
283
284
|
Returns:
|
284
285
|
Portfolio optimization result
|
285
286
|
|
@@ -300,7 +301,7 @@ class QuantumPortfolioAgent(QuantumAgent):
|
|
300
301
|
|
301
302
|
elif method == 'qaoa':
|
302
303
|
# Use QAOA for discrete optimization
|
303
|
-
|
304
|
+
self.algorithms['qaoa'].optimize(lambda x: self._portfolio_objective(x))
|
304
305
|
optimal_solution = self.algorithms['qaoa'].predict(problem_instance)
|
305
306
|
|
306
307
|
# Convert binary solution to weights
|
@@ -398,11 +399,11 @@ class QuantumPortfolioAgent(QuantumAgent):
|
|
398
399
|
|
399
400
|
class QuantumClassificationAgent(QuantumAgent):
|
400
401
|
"""Quantum agent for classification tasks.
|
401
|
-
|
402
|
+
|
402
403
|
This agent combines multiple quantum classifiers and provides
|
403
404
|
automatic model selection, hyperparameter optimization, and
|
404
405
|
ensemble methods for robust classification.
|
405
|
-
|
406
|
+
|
406
407
|
Args:
|
407
408
|
backend: Quantum backend
|
408
409
|
algorithms: List of algorithms to include ('quantum_svm', 'quantum_nn', 'hybrid')
|
@@ -414,8 +415,8 @@ class QuantumClassificationAgent(QuantumAgent):
|
|
414
415
|
|
415
416
|
def __init__(
|
416
417
|
self,
|
417
|
-
backend:
|
418
|
-
algorithms:
|
418
|
+
backend: str | Any,
|
419
|
+
algorithms: list[str] | None = None,
|
419
420
|
ensemble_method: str = 'voting',
|
420
421
|
auto_tune: bool = False,
|
421
422
|
**kwargs
|
@@ -502,7 +503,7 @@ class QuantumClassificationAgent(QuantumAgent):
|
|
502
503
|
best_algo = max(self.performance_metrics.items(), key=lambda x: x[1])[0]
|
503
504
|
return predictions.get(best_algo, list(predictions.values())[0])
|
504
505
|
|
505
|
-
def _majority_voting(self, predictions:
|
506
|
+
def _majority_voting(self, predictions: dict[str, np.ndarray]) -> np.ndarray:
|
506
507
|
"""Majority voting ensemble."""
|
507
508
|
pred_arrays = list(predictions.values())
|
508
509
|
n_samples = len(pred_arrays[0])
|
@@ -515,7 +516,7 @@ class QuantumClassificationAgent(QuantumAgent):
|
|
515
516
|
|
516
517
|
return np.array(final_predictions)
|
517
518
|
|
518
|
-
def _weighted_voting(self, predictions:
|
519
|
+
def _weighted_voting(self, predictions: dict[str, np.ndarray]) -> np.ndarray:
|
519
520
|
"""Weighted voting based on performance."""
|
520
521
|
weights = {}
|
521
522
|
total_weight = 0
|
@@ -548,7 +549,7 @@ class QuantumClassificationAgent(QuantumAgent):
|
|
548
549
|
|
549
550
|
return np.array(final_predictions)
|
550
551
|
|
551
|
-
def solve(self, problem_instance:
|
552
|
+
def solve(self, problem_instance: tuple[np.ndarray, np.ndarray], **kwargs) -> QuantumResult:
|
552
553
|
"""Solve classification problem."""
|
553
554
|
import time
|
554
555
|
|
@@ -595,11 +596,11 @@ class QuantumClassificationAgent(QuantumAgent):
|
|
595
596
|
|
596
597
|
class QuantumTradingAgent(QuantumAgent):
|
597
598
|
"""Autonomous quantum trading agent for financial markets.
|
598
|
-
|
599
|
+
|
599
600
|
This agent combines quantum portfolio optimization, quantum risk analysis,
|
600
601
|
and quantum-enhanced pattern recognition to make autonomous trading
|
601
602
|
decisions with potential quantum advantages in complex market scenarios.
|
602
|
-
|
603
|
+
|
603
604
|
Args:
|
604
605
|
backend: Quantum backend for computations
|
605
606
|
strategy: Trading strategy ('momentum', 'mean_reversion', 'quantum_portfolio')
|
@@ -612,11 +613,11 @@ class QuantumTradingAgent(QuantumAgent):
|
|
612
613
|
|
613
614
|
def __init__(
|
614
615
|
self,
|
615
|
-
backend:
|
616
|
+
backend: str | Any = 'auto',
|
616
617
|
strategy: str = 'quantum_portfolio',
|
617
618
|
risk_tolerance: float = 0.5,
|
618
619
|
quantum_advantage_threshold: float = 0.05,
|
619
|
-
markets:
|
620
|
+
markets: list[str] | None = None,
|
620
621
|
**kwargs
|
621
622
|
) -> None:
|
622
623
|
super().__init__(backend=backend, **kwargs)
|
@@ -640,7 +641,7 @@ class QuantumTradingAgent(QuantumAgent):
|
|
640
641
|
"""Initialize the trading agent."""
|
641
642
|
self.is_fitted = True # Agents are pre-configured
|
642
643
|
|
643
|
-
def fit(self, X: np.ndarray, y:
|
644
|
+
def fit(self, X: np.ndarray, y: np.ndarray | None = None, **kwargs) -> 'QuantumTradingAgent':
|
644
645
|
"""Fit the trading agent (optional for pre-configured agents)."""
|
645
646
|
return self
|
646
647
|
|
@@ -653,7 +654,7 @@ class QuantumTradingAgent(QuantumAgent):
|
|
653
654
|
"""Solve trading optimization problem."""
|
654
655
|
return self.deploy(problem_instance, **kwargs)
|
655
656
|
|
656
|
-
def deploy(self, market_data:
|
657
|
+
def deploy(self, market_data: Any | None = None, **kwargs) -> QuantumResult:
|
657
658
|
"""Deploy the trading agent and return performance metrics."""
|
658
659
|
start_time = time.time()
|
659
660
|
|
@@ -693,7 +694,7 @@ class QuantumTradingAgent(QuantumAgent):
|
|
693
694
|
error=str(e),
|
694
695
|
)
|
695
696
|
|
696
|
-
def _quantum_portfolio_optimization(self, market_data: Any, **kwargs) ->
|
697
|
+
def _quantum_portfolio_optimization(self, market_data: Any, **kwargs) -> dict[str, Any]:
|
697
698
|
"""Perform quantum portfolio optimization."""
|
698
699
|
# Placeholder implementation
|
699
700
|
return {
|
@@ -702,7 +703,7 @@ class QuantumTradingAgent(QuantumAgent):
|
|
702
703
|
'sharpe_ratio': 0.8 + np.random.normal(0, 0.1),
|
703
704
|
}
|
704
705
|
|
705
|
-
def _quantum_momentum_strategy(self, market_data: Any, **kwargs) ->
|
706
|
+
def _quantum_momentum_strategy(self, market_data: Any, **kwargs) -> dict[str, Any]:
|
706
707
|
"""Quantum-enhanced momentum trading strategy."""
|
707
708
|
return {
|
708
709
|
'expected_return': 0.10 + np.random.normal(0, 0.03),
|
@@ -710,7 +711,7 @@ class QuantumTradingAgent(QuantumAgent):
|
|
710
711
|
'sharpe_ratio': 0.6 + np.random.normal(0, 0.1),
|
711
712
|
}
|
712
713
|
|
713
|
-
def _basic_trading_strategy(self, market_data: Any, **kwargs) ->
|
714
|
+
def _basic_trading_strategy(self, market_data: Any, **kwargs) -> dict[str, Any]:
|
714
715
|
"""Basic trading strategy fallback."""
|
715
716
|
return {
|
716
717
|
'expected_return': 0.08 + np.random.normal(0, 0.02),
|
@@ -718,7 +719,7 @@ class QuantumTradingAgent(QuantumAgent):
|
|
718
719
|
'sharpe_ratio': 0.4 + np.random.normal(0, 0.05),
|
719
720
|
}
|
720
721
|
|
721
|
-
def _calculate_quantum_advantage(self, result:
|
722
|
+
def _calculate_quantum_advantage(self, result: dict[str, Any]) -> float:
|
722
723
|
"""Calculate quantum advantage over classical methods."""
|
723
724
|
# Simplified quantum advantage calculation
|
724
725
|
base_performance = 0.08 # Classical baseline
|
@@ -728,11 +729,11 @@ class QuantumTradingAgent(QuantumAgent):
|
|
728
729
|
|
729
730
|
class QuantumResearchAgent(QuantumAgent):
|
730
731
|
"""Autonomous quantum research agent for scientific discovery.
|
731
|
-
|
732
|
-
This agent combines quantum simulation, quantum machine learning, and
|
732
|
+
|
733
|
+
This agent combines quantum simulation, quantum machine learning, and
|
733
734
|
automated hypothesis generation to accelerate scientific research across
|
734
735
|
domains like materials science, drug discovery, and physics.
|
735
|
-
|
736
|
+
|
736
737
|
Args:
|
737
738
|
backend: Quantum backend for simulations
|
738
739
|
domain: Research domain ('materials_science', 'drug_discovery', 'physics')
|
@@ -745,7 +746,7 @@ class QuantumResearchAgent(QuantumAgent):
|
|
745
746
|
|
746
747
|
def __init__(
|
747
748
|
self,
|
748
|
-
backend:
|
749
|
+
backend: str | Any = 'auto',
|
749
750
|
domain: str = 'materials_science',
|
750
751
|
hypothesis_generation: bool = True,
|
751
752
|
experiment_design: bool = True,
|
@@ -784,7 +785,7 @@ class QuantumResearchAgent(QuantumAgent):
|
|
784
785
|
"""Initialize the research agent."""
|
785
786
|
self.is_fitted = True # Agents are pre-configured
|
786
787
|
|
787
|
-
def fit(self, X: np.ndarray, y:
|
788
|
+
def fit(self, X: np.ndarray, y: np.ndarray | None = None, **kwargs) -> 'QuantumResearchAgent':
|
788
789
|
"""Fit the research agent (optional for pre-configured agents)."""
|
789
790
|
return self
|
790
791
|
|
@@ -800,7 +801,7 @@ class QuantumResearchAgent(QuantumAgent):
|
|
800
801
|
def investigate(
|
801
802
|
self,
|
802
803
|
research_question: str,
|
803
|
-
constraints:
|
804
|
+
constraints: dict[str, Any] | None = None,
|
804
805
|
**kwargs
|
805
806
|
) -> QuantumResult:
|
806
807
|
"""Investigate a research question and return research plan."""
|
@@ -841,7 +842,7 @@ class QuantumResearchAgent(QuantumAgent):
|
|
841
842
|
error=str(e),
|
842
843
|
)
|
843
844
|
|
844
|
-
def _generate_research_plan(self, question: str, constraints:
|
845
|
+
def _generate_research_plan(self, question: str, constraints: dict[str, Any] | None) -> dict[str, Any]:
|
845
846
|
"""Generate a research plan using quantum-enhanced methods."""
|
846
847
|
constraints = constraints or {}
|
847
848
|
|
@@ -859,7 +860,7 @@ class QuantumResearchAgent(QuantumAgent):
|
|
859
860
|
'expected_quantum_advantage': 'Exponential speedup for molecular simulations',
|
860
861
|
}
|
861
862
|
|
862
|
-
def _generate_hypothesis(self, question: str) ->
|
863
|
+
def _generate_hypothesis(self, question: str) -> dict[str, Any]:
|
863
864
|
"""Generate research hypotheses using quantum ML."""
|
864
865
|
return {
|
865
866
|
'primary_hypothesis': f"Quantum effects in {self.domain} can be leveraged to solve: {question}",
|
@@ -873,7 +874,7 @@ class QuantumResearchAgent(QuantumAgent):
|
|
873
874
|
]
|
874
875
|
}
|
875
876
|
|
876
|
-
def _design_experiments(self, question: str) ->
|
877
|
+
def _design_experiments(self, question: str) -> list[dict[str, Any]]:
|
877
878
|
"""Design quantum experiments for research validation."""
|
878
879
|
return [
|
879
880
|
{
|
@@ -894,11 +895,11 @@ class QuantumResearchAgent(QuantumAgent):
|
|
894
895
|
|
895
896
|
class QuantumOptimizationAgent(QuantumAgent):
|
896
897
|
"""Quantum agent for optimization problems.
|
897
|
-
|
898
|
+
|
898
899
|
This agent provides a unified interface for solving various
|
899
900
|
optimization problems using QAOA, VQE, and other quantum
|
900
901
|
optimization algorithms.
|
901
|
-
|
902
|
+
|
902
903
|
Args:
|
903
904
|
backend: Quantum backend
|
904
905
|
problem_type: Type of optimization ('combinatorial', 'continuous', 'mixed')
|
@@ -909,9 +910,9 @@ class QuantumOptimizationAgent(QuantumAgent):
|
|
909
910
|
|
910
911
|
def __init__(
|
911
912
|
self,
|
912
|
-
backend:
|
913
|
+
backend: str | Any,
|
913
914
|
problem_type: str = 'combinatorial',
|
914
|
-
algorithms:
|
915
|
+
algorithms: list[str] | None = None,
|
915
916
|
**kwargs
|
916
917
|
) -> None:
|
917
918
|
agent_config = {
|
@@ -940,7 +941,7 @@ class QuantumOptimizationAgent(QuantumAgent):
|
|
940
941
|
shots=self.shots
|
941
942
|
)
|
942
943
|
|
943
|
-
def fit(self, X: np.ndarray, y:
|
944
|
+
def fit(self, X: np.ndarray, y: np.ndarray | None = None, **kwargs) -> 'QuantumOptimizationAgent':
|
944
945
|
"""Fit optimization algorithms to problem."""
|
945
946
|
for name, algorithm in self.algorithms.items():
|
946
947
|
algorithm.fit(X, y)
|
@@ -5,7 +5,7 @@ quantum distance calculations and quantum amplitude estimation approaches.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import logging
|
8
|
-
from typing import Any
|
8
|
+
from typing import Any
|
9
9
|
|
10
10
|
import numpy as np
|
11
11
|
from sklearn.cluster import KMeans
|
@@ -19,17 +19,17 @@ logger = logging.getLogger(__name__)
|
|
19
19
|
|
20
20
|
class QuantumKMeans(UnsupervisedQuantumAlgorithm):
|
21
21
|
"""Quantum K-Means clustering algorithm.
|
22
|
-
|
22
|
+
|
23
23
|
This implementation uses quantum algorithms to perform K-means clustering,
|
24
24
|
potentially offering speedup for high-dimensional data through quantum
|
25
25
|
distance calculations and amplitude estimation.
|
26
|
-
|
26
|
+
|
27
27
|
The algorithm can use different quantum approaches:
|
28
28
|
- Quantum Distance Calculation: Use quantum circuits to compute distances
|
29
29
|
- Quantum Amplitude Estimation: For probabilistic distance measurements
|
30
30
|
- Variational Quantum Clustering: Use VQC for cluster optimization
|
31
31
|
- Quantum Annealing: For global cluster optimization
|
32
|
-
|
32
|
+
|
33
33
|
Args:
|
34
34
|
backend: Quantum backend for circuit execution
|
35
35
|
n_clusters: Number of clusters (k)
|
@@ -42,7 +42,7 @@ class QuantumKMeans(UnsupervisedQuantumAlgorithm):
|
|
42
42
|
shots: Number of measurement shots
|
43
43
|
classical_fallback: Use classical K-means if quantum fails
|
44
44
|
**kwargs: Additional parameters
|
45
|
-
|
45
|
+
|
46
46
|
Example:
|
47
47
|
>>> qkmeans = QuantumKMeans(backend='pennylane', n_clusters=3, method='distance')
|
48
48
|
>>> qkmeans.fit(X_train)
|
@@ -53,7 +53,7 @@ class QuantumKMeans(UnsupervisedQuantumAlgorithm):
|
|
53
53
|
|
54
54
|
def __init__(
|
55
55
|
self,
|
56
|
-
backend:
|
56
|
+
backend: str | Any,
|
57
57
|
n_clusters: int = 3,
|
58
58
|
method: str = 'distance',
|
59
59
|
distance_metric: str = 'euclidean',
|
@@ -64,7 +64,7 @@ class QuantumKMeans(UnsupervisedQuantumAlgorithm):
|
|
64
64
|
shots: int = 1024,
|
65
65
|
classical_fallback: bool = True,
|
66
66
|
normalize_data: bool = True,
|
67
|
-
random_state:
|
67
|
+
random_state: int | None = None,
|
68
68
|
**kwargs
|
69
69
|
) -> None:
|
70
70
|
super().__init__(backend=backend, shots=shots, **kwargs)
|
@@ -326,14 +326,14 @@ class QuantumKMeans(UnsupervisedQuantumAlgorithm):
|
|
326
326
|
centroid_shift = np.max(np.linalg.norm(new_centroids - old_centroids, axis=1))
|
327
327
|
return centroid_shift < self.tolerance
|
328
328
|
|
329
|
-
def fit(self, X: np.ndarray, y:
|
329
|
+
def fit(self, X: np.ndarray, y: np.ndarray | None = None, **kwargs) -> 'QuantumKMeans':
|
330
330
|
"""Fit quantum K-means to the data.
|
331
|
-
|
331
|
+
|
332
332
|
Args:
|
333
333
|
X: Training data
|
334
334
|
y: Ignored (unsupervised learning)
|
335
335
|
**kwargs: Additional fitting parameters
|
336
|
-
|
336
|
+
|
337
337
|
Returns:
|
338
338
|
Self for method chaining
|
339
339
|
|
@@ -401,11 +401,11 @@ class QuantumKMeans(UnsupervisedQuantumAlgorithm):
|
|
401
401
|
|
402
402
|
def predict(self, X: np.ndarray, **kwargs) -> np.ndarray:
|
403
403
|
"""Predict cluster labels for new data.
|
404
|
-
|
404
|
+
|
405
405
|
Args:
|
406
406
|
X: Data to cluster
|
407
407
|
**kwargs: Additional parameters
|
408
|
-
|
408
|
+
|
409
409
|
Returns:
|
410
410
|
Cluster labels
|
411
411
|
|
@@ -423,7 +423,7 @@ class QuantumKMeans(UnsupervisedQuantumAlgorithm):
|
|
423
423
|
# Assign to nearest cluster
|
424
424
|
return self._assign_clusters(distances)
|
425
425
|
|
426
|
-
def fit_predict(self, X: np.ndarray, y:
|
426
|
+
def fit_predict(self, X: np.ndarray, y: np.ndarray | None = None) -> np.ndarray:
|
427
427
|
"""Fit K-means and return cluster labels."""
|
428
428
|
return self.fit(X, y).labels_
|
429
429
|
|
@@ -439,7 +439,7 @@ class QuantumKMeans(UnsupervisedQuantumAlgorithm):
|
|
439
439
|
# Return distances to all centroids
|
440
440
|
return self._compute_distances_batch(X, self.cluster_centers_)
|
441
441
|
|
442
|
-
def get_quantum_advantage_metrics(self) ->
|
442
|
+
def get_quantum_advantage_metrics(self) -> dict[str, Any]:
|
443
443
|
"""Analyze potential quantum advantage."""
|
444
444
|
if not self.is_fitted:
|
445
445
|
raise ValueError("Must fit model first")
|
@@ -467,7 +467,7 @@ class QuantumKMeans(UnsupervisedQuantumAlgorithm):
|
|
467
467
|
|
468
468
|
return metrics
|
469
469
|
|
470
|
-
def compare_with_classical(self, X: np.ndarray, y_true:
|
470
|
+
def compare_with_classical(self, X: np.ndarray, y_true: np.ndarray | None = None) -> dict[str, Any]:
|
471
471
|
"""Compare quantum K-means results with classical K-means."""
|
472
472
|
if not self.is_fitted or not hasattr(self.classical_kmeans, 'cluster_centers_'):
|
473
473
|
raise ValueError("Both quantum and classical K-means must be fitted")
|
@@ -531,7 +531,7 @@ class QuantumKMeans(UnsupervisedQuantumAlgorithm):
|
|
531
531
|
|
532
532
|
return comparison
|
533
533
|
|
534
|
-
def analyze_convergence(self) ->
|
534
|
+
def analyze_convergence(self) -> dict[str, Any]:
|
535
535
|
"""Analyze convergence properties."""
|
536
536
|
if not self.convergence_history:
|
537
537
|
return {'message': 'No convergence history available'}
|
@@ -548,7 +548,7 @@ class QuantumKMeans(UnsupervisedQuantumAlgorithm):
|
|
548
548
|
'inertia_variance': np.var(inertias[-10:]) if len(inertias) >= 10 else np.var(inertias),
|
549
549
|
}
|
550
550
|
|
551
|
-
def get_params(self, deep: bool = True) ->
|
551
|
+
def get_params(self, deep: bool = True) -> dict[str, Any]:
|
552
552
|
"""Get quantum K-means parameters."""
|
553
553
|
params = super().get_params(deep)
|
554
554
|
params.update({
|
@@ -5,7 +5,7 @@ tasks using parameterized quantum circuits as trainable layers.
|
|
5
5
|
"""
|
6
6
|
|
7
7
|
import logging
|
8
|
-
from typing import Any
|
8
|
+
from typing import Any
|
9
9
|
|
10
10
|
import numpy as np
|
11
11
|
from sklearn.metrics import accuracy_score
|
@@ -18,15 +18,15 @@ logger = logging.getLogger(__name__)
|
|
18
18
|
|
19
19
|
class QuantumNN(SupervisedQuantumAlgorithm):
|
20
20
|
"""Quantum Neural Network for classification and regression.
|
21
|
-
|
21
|
+
|
22
22
|
This implementation uses parameterized quantum circuits as neural network
|
23
23
|
layers, with classical optimization to train the quantum parameters.
|
24
|
-
|
24
|
+
|
25
25
|
The network can be configured with different architectures:
|
26
26
|
- Pure quantum: Only quantum layers
|
27
|
-
- Hybrid: Combination of quantum and classical layers
|
27
|
+
- Hybrid: Combination of quantum and classical layers
|
28
28
|
- Variational: Variational quantum circuits with measurement
|
29
|
-
|
29
|
+
|
30
30
|
Args:
|
31
31
|
backend: Quantum backend for circuit execution
|
32
32
|
n_layers: Number of quantum layers
|
@@ -39,7 +39,7 @@ class QuantumNN(SupervisedQuantumAlgorithm):
|
|
39
39
|
batch_size: Training batch size
|
40
40
|
shots: Number of measurement shots
|
41
41
|
**kwargs: Additional parameters
|
42
|
-
|
42
|
+
|
43
43
|
Example:
|
44
44
|
>>> qnn = QuantumNN(backend='pennylane', n_layers=3, architecture='hybrid')
|
45
45
|
>>> qnn.fit(X_train, y_train)
|
@@ -50,7 +50,7 @@ class QuantumNN(SupervisedQuantumAlgorithm):
|
|
50
50
|
|
51
51
|
def __init__(
|
52
52
|
self,
|
53
|
-
backend:
|
53
|
+
backend: str | Any,
|
54
54
|
n_layers: int = 3,
|
55
55
|
architecture: str = 'hybrid',
|
56
56
|
encoding: str = 'angle',
|
@@ -225,11 +225,11 @@ class QuantumNN(SupervisedQuantumAlgorithm):
|
|
225
225
|
|
226
226
|
def _forward_pass(self, x: np.ndarray, weights: np.ndarray) -> np.ndarray:
|
227
227
|
"""Perform forward pass through the quantum neural network.
|
228
|
-
|
228
|
+
|
229
229
|
Args:
|
230
230
|
x: Input data
|
231
231
|
weights: Network weights
|
232
|
-
|
232
|
+
|
233
233
|
Returns:
|
234
234
|
Network output
|
235
235
|
|
@@ -324,12 +324,12 @@ class QuantumNN(SupervisedQuantumAlgorithm):
|
|
324
324
|
|
325
325
|
def fit(self, X: np.ndarray, y: np.ndarray, **kwargs) -> 'QuantumNN':
|
326
326
|
"""Train the quantum neural network.
|
327
|
-
|
327
|
+
|
328
328
|
Args:
|
329
329
|
X: Training data features
|
330
330
|
y: Training data labels
|
331
331
|
**kwargs: Additional training parameters
|
332
|
-
|
332
|
+
|
333
333
|
Returns:
|
334
334
|
Self for method chaining
|
335
335
|
|
@@ -429,11 +429,11 @@ class QuantumNN(SupervisedQuantumAlgorithm):
|
|
429
429
|
|
430
430
|
def predict(self, X: np.ndarray, **kwargs) -> np.ndarray:
|
431
431
|
"""Make predictions using the trained quantum neural network.
|
432
|
-
|
432
|
+
|
433
433
|
Args:
|
434
434
|
X: Input data for prediction
|
435
435
|
**kwargs: Additional prediction parameters
|
436
|
-
|
436
|
+
|
437
437
|
Returns:
|
438
438
|
Predicted labels or values
|
439
439
|
|
@@ -459,11 +459,11 @@ class QuantumNN(SupervisedQuantumAlgorithm):
|
|
459
459
|
|
460
460
|
def predict_proba(self, X: np.ndarray, **kwargs) -> np.ndarray:
|
461
461
|
"""Predict class probabilities.
|
462
|
-
|
462
|
+
|
463
463
|
Args:
|
464
464
|
X: Input data for prediction
|
465
465
|
**kwargs: Additional parameters
|
466
|
-
|
466
|
+
|
467
467
|
Returns:
|
468
468
|
Predicted class probabilities
|
469
469
|
|
@@ -487,14 +487,14 @@ class QuantumNN(SupervisedQuantumAlgorithm):
|
|
487
487
|
else:
|
488
488
|
return self.n_layers * 2 # Estimate
|
489
489
|
|
490
|
-
def get_training_history(self) ->
|
490
|
+
def get_training_history(self) -> dict[str, list[float]]:
|
491
491
|
"""Get training history."""
|
492
492
|
history = {'loss': self.loss_history}
|
493
493
|
if self.accuracy_history:
|
494
494
|
history['accuracy'] = self.accuracy_history
|
495
495
|
return history
|
496
496
|
|
497
|
-
def analyze_expressivity(self) ->
|
497
|
+
def analyze_expressivity(self) -> dict[str, Any]:
|
498
498
|
"""Analyze the expressivity of the quantum neural network."""
|
499
499
|
analysis = {
|
500
500
|
'n_qubits': self.n_qubits,
|
@@ -514,7 +514,7 @@ class QuantumNN(SupervisedQuantumAlgorithm):
|
|
514
514
|
|
515
515
|
return analysis
|
516
516
|
|
517
|
-
def get_params(self, deep: bool = True) ->
|
517
|
+
def get_params(self, deep: bool = True) -> dict[str, Any]:
|
518
518
|
"""Get quantum neural network parameters."""
|
519
519
|
params = super().get_params(deep)
|
520
520
|
params.update({
|