luna-quantum 0.0.33__py3-none-any.whl → 0.10.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.

Potentially problematic release.


This version of luna-quantum might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: luna-quantum
3
- Version: 0.0.33
3
+ Version: 0.10.1
4
4
  Summary: Python SDK for Aqarios' Luna Platform
5
5
  Home-page: https://aqarios.com/
6
6
  License: Apache-2.0
@@ -1,20 +1,20 @@
1
1
  luna_sdk/__init__.py,sha256=9s6JkcSeRF4WtFo80TelzXXHFhX8w7fXiaJr59V9ScM,100
2
2
  luna_sdk/controllers/__init__.py,sha256=ivTapH8np5mQeVEevxwsWawCtVSG4Wep72rNp7nEZXw,60
3
3
  luna_sdk/controllers/luna_http_client.py,sha256=_q3_o-bjC61uQMnNTfbbGei0eNR_AoIv-2R1cYRfEgU,819
4
- luna_sdk/controllers/luna_platform_client.py,sha256=EH1jxruuRKwaJ1Vos79PGT4-hwp7jdoSaRFKqjUMbZA,2406
4
+ luna_sdk/controllers/luna_platform_client.py,sha256=TUeK9hlbY3LdYkl0UO2FJtCzGFuU8lshA-kdutkDZlM,2406
5
5
  luna_sdk/controllers/luna_q.py,sha256=cv28o2fYDSaI8iAsfMYWtR68mfuUDxY3jmBWY2KnkRk,1199
6
6
  luna_sdk/controllers/luna_solve.py,sha256=ioMdB7Rlx-1-XB5WE5OT8oVlO_T1l5T64R-ccaNUCAA,1797
7
7
  luna_sdk/controllers/luna_transform.py,sha256=7kdIp5oRMG1NQZ1hBSkcNrj-z6g_2dWvQZ4j8BK3M0A,1337
8
8
  luna_sdk/error/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  luna_sdk/error/http_error_utils.py,sha256=qZ4a43GVR35-bn3QTVmGZBJzEjieo43r36M2G5rfIyw,3509
10
10
  luna_sdk/exceptions/__init__.py,sha256=DSKaPN374rR2zccmpLvlqntxDsjFwgSexXtva795ae0,52
11
- luna_sdk/exceptions/encryption_exception.py,sha256=qe38EPRen4c63ti6bbA3jXl4PK48Ommi_cb2Lvhn8tg,264
11
+ luna_sdk/exceptions/encryption_exception.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  luna_sdk/exceptions/luna_exception.py,sha256=m7U3qFpP9Sc77Z3RG9I4bQXsJSQuVeBLvfHQWziC9sQ,114
13
13
  luna_sdk/exceptions/luna_server_exception.py,sha256=y4J1TzfMF_kmuh5g8hpP2k_SnV0acaxks8lg5EOvo0I,639
14
14
  luna_sdk/exceptions/timeout_exception.py,sha256=ppEGsUk-6NtBy2-RyBfzjR1IhDmIwPWwg03BOsET4OA,367
15
15
  luna_sdk/exceptions/transformation.py,sha256=lykEeWonvfvWAyU2DoKzR-GtFc-KEAvrfWlnWT9ylqc,381
16
16
  luna_sdk/interfaces/__init__.py,sha256=WwAzuNWP6SNMJk_U_Hqc5U2mRsG2_m-sSQZPMYUDWfY,213
17
- luna_sdk/interfaces/circuit_repo_i.py,sha256=65SSefsrpo_MKFTGkdT1o5PJ7pQ9n9tmSnunoQ_Mruo,1946
17
+ luna_sdk/interfaces/circuit_repo_i.py,sha256=Y3PZQDILT016UNwORBg51sgHFnDxMTgfQ0JXmEowoK0,1642
18
18
  luna_sdk/interfaces/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  luna_sdk/interfaces/clients/client_i.py,sha256=_I8mTIfavI3Yv7TPD9HsTxF3uI4WzDucFvgEb2EtOAo,185
20
20
  luna_sdk/interfaces/clients/luna_q_i.py,sha256=_DHDirve9yoVO8zb5i3WkTMx-LPu9TtasjF4OUfCaRw,765
@@ -24,36 +24,37 @@ luna_sdk/interfaces/cplex_repo_i.py,sha256=a2CWG1m4YmQAlcM022Xfk09BHVmcd3y2H-GMr
24
24
  luna_sdk/interfaces/info_repo_i.py,sha256=hCUYNoqjAKwz6l-61XtymX-UboosDX1RaTTiX64EXXc,1345
25
25
  luna_sdk/interfaces/lp_repo_i.py,sha256=hixIKvJ8jz9VOUi33B3K2VvFLcR7eKfeooJwktquyhc,3052
26
26
  luna_sdk/interfaces/optimization_repo_i.py,sha256=4JZikxWTJZTX4tG85ydSP711WROQ5B8RtbvOp1EDvxE,6202
27
- luna_sdk/interfaces/qpu_token_repo_i.py,sha256=q5aWiGxFnuRSasgHcceRAjQ0NvMPRoBfkeJHCByBy_0,4626
27
+ luna_sdk/interfaces/qpu_token_repo_i.py,sha256=oTxYxoeMOPJUV4-U1Fd1kD76EVPGmi1Sp9C1J4cvffY,11418
28
28
  luna_sdk/interfaces/repository_i.py,sha256=vJz8pbggkuLLC333qzjepj3TMPh49LUnyh3pJDlcGi0,287
29
- luna_sdk/interfaces/solutions_repo_i.py,sha256=YmQxgDGSLZNQ-P7jzlw1zTnut5Q1KVeRbcJEuocB3VQ,7767
29
+ luna_sdk/interfaces/solutions_repo_i.py,sha256=uSAClqt_zfg-k9VvVn8DfkG2vE2NXyCqaxRlaK8mCb4,8012
30
30
  luna_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  luna_sdk/repositories/__init__.py,sha256=HxD02fpzlcIt5YkBHd7LwIp_eE6eFuAz2VDnlrakwJQ,169
32
- luna_sdk/repositories/circuit_repo.py,sha256=h3Moypl-pba8J-sNTBsOxnbKtu6RCmmX5c_4JnfQfCw,2552
32
+ luna_sdk/repositories/circuit_repo.py,sha256=gpjEmCRrl8UghJrelOt6VOULIJmM-thJAhf8oaA5Ckg,1964
33
33
  luna_sdk/repositories/cplex_repo.py,sha256=6vlx6YTJoDSWFSZDDNrPk3E7pa5WWGqG25bhTwQdqHQ,5098
34
34
  luna_sdk/repositories/info_repo.py,sha256=GzRW5RwhRJrNjujw8Y7vJY8vV_tHzbfwXo0viHuxqUM,1270
35
35
  luna_sdk/repositories/lp_repo.py,sha256=T44XMbdbW7k9a4z6JgIj1kb0bBZxepn-93vxdZOQa80,4370
36
36
  luna_sdk/repositories/optimization_repo.py,sha256=xHjMdXhzdwt9DtZG7AvGtUgOqWH142veOpAzaNe-nxk,6078
37
- luna_sdk/repositories/qpu_token_repo.py,sha256=6V3PH2YLMoWx6Dv6hxDoe2ohXH2mRN37nfvzVS6bHDA,5063
38
- luna_sdk/repositories/solutions_repo.py,sha256=Q5Q30oRyUnayXkp4z_jPcjDpxYRoPjzWBWUqg2EAFWQ,9242
37
+ luna_sdk/repositories/qpu_token_repo.py,sha256=_qM9dJB23AR1-Kblx_yJcovYmuYwGcZMjH2va19F8yg,8840
38
+ luna_sdk/repositories/solutions_repo.py,sha256=W-VHmhN6wkL3jSg4FE0IyVLydatLE7LjqI-RhP21XFs,9073
39
39
  luna_sdk/schemas/__init__.py,sha256=lTix3zUl2Z8ZLA2BTF4pls5S-kqlVZ3cIdAZwGxPSUI,248
40
40
  luna_sdk/schemas/circuit.py,sha256=r3Bv0lyhrvFoI3Gf8eq-PS3kyivTWY3IJmRH0X2LoCk,1067
41
- luna_sdk/schemas/create/__init__.py,sha256=7G2yflImpZJxHn3l4Op5CsQAxwKGmvWJSttq9kmiHq0,90
42
- luna_sdk/schemas/create/circuit.py,sha256=vV2r6xk24_aHe9oo0dt3wVeOHcyD02lXNR-YyjfQoEE,755
41
+ luna_sdk/schemas/create/__init__.py,sha256=WTthzwyS0PI2zSENoHp7EWLciLz_DyFebCzSCFVensU,144
42
+ luna_sdk/schemas/create/circuit.py,sha256=zYtM6SV1QH4JzjYaAhrGNjdNn8EDYsdG1QKwayTqkEY,643
43
43
  luna_sdk/schemas/create/optimization.py,sha256=Z9pKoD0y6BjKvl8gQ6XK76bdvq8etvcoNU4RwxnUvHA,759
44
- luna_sdk/schemas/create/qpu_token.py,sha256=XE3WoNL3Q8QFEDshXoSrAKQXgT_zthKvihKqJHi8250,492
44
+ luna_sdk/schemas/create/qpu_token.py,sha256=_D_QtYOeZQ6b0lG5ALTDmyr4bU42bUZ8OJ0VdwadMNA,380
45
+ luna_sdk/schemas/create/qpu_token_time_quota.py,sha256=5HyfYuXGZmpqB-j4yuStFc7V3b7niPYHYb0KIuvJAzQ,650
45
46
  luna_sdk/schemas/create/qubo.py,sha256=5Y_jWicEnoV82Ubc-f0a_qy9hCuPBumhsGWY8wzMIuA,293
46
- luna_sdk/schemas/create/solution.py,sha256=K97JHH-p5z0P_niTVX6YBPoDc0rgIpJG5O4uaUhcs48,410
47
+ luna_sdk/schemas/create/solution.py,sha256=zPPgm0wGwfn23ccgBoYs6SMTZNmbT_uO1po_je15WjA,386
47
48
  luna_sdk/schemas/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
49
  luna_sdk/schemas/enums/circuit.py,sha256=smz_DouDo_K8rs4N5aIOj2PS9w6DX1CFYX0bv6f6JFw,252
49
50
  luna_sdk/schemas/enums/optimization.py,sha256=XtFdcfLxGe-MAL64itjxszhRkTcUzUf83tO-5DBVLeY,198
50
51
  luna_sdk/schemas/enums/problem.py,sha256=HWL6Lc1pqPtJ0J-rXkUTL6WHe2fiBY1ctuZvDnx1hmM,754
51
52
  luna_sdk/schemas/enums/qpu_token_type.py,sha256=KBRrB8ExuTTmpp48obxdJGWwWEHb7xgq9Ajjwptl1VY,105
52
53
  luna_sdk/schemas/enums/solution.py,sha256=Vax6MX62UDwApbwzf1nrhuFWw1Iiq77gUch7_1roCYo,114
53
- luna_sdk/schemas/enums/status.py,sha256=KHaOgePqB3GNhFYLo2Sp-JAEXBPN_ZVDmj2WobrT5N4,204
54
+ luna_sdk/schemas/enums/status.py,sha256=D0ZEu6Bg0GspDrjujwrtRAmkF50m2cUT-b0MOiAi4sg,227
54
55
  luna_sdk/schemas/enums/timeframe.py,sha256=vwoZsgAYGvqF67qdcXMEnHkqbiRcVY5uK-4-ZTFcurI,238
55
56
  luna_sdk/schemas/error_message.py,sha256=svCs-mWQsp3BMEhzZFqskbyP6iS78eVUOPaiWFc4sEQ,307
56
- luna_sdk/schemas/optimization.py,sha256=pCbDL93PFGf7IOGz-0PHFrrpOwQdszm78WnS0oo2xqU,1884
57
+ luna_sdk/schemas/optimization.py,sha256=juFzE7UUAnLoLvZneOwpXzzhsSUQ2dpXIX48Bm0Sdzg,3172
57
58
  luna_sdk/schemas/optimization_formats/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
59
  luna_sdk/schemas/optimization_formats/bqm.py,sha256=rrmiZYe_iEdgBFusJeJfY8PVSxgf1Wv79FgMQUm2YVs,910
59
60
  luna_sdk/schemas/optimization_formats/cqm.py,sha256=VZiNJy4yc-8o3gHoH0E-uaNOHj7UfAGCqznTzKBv0NQ,4257
@@ -62,19 +63,20 @@ luna_sdk/schemas/optimization_formats/qm.py,sha256=yUEZF7FOvXv1Mb5FMiX1q0Rk5w2lt
62
63
  luna_sdk/schemas/optimization_formats/qubo.py,sha256=YN-VbPGTgqOKJuJ7t_TT8H_WIWr1ifU974K98W9Blao,135
63
64
  luna_sdk/schemas/pretty_base.py,sha256=ZyVdwdY5JfmNlfqZDm6MdTs5roNGtv0Pe805r4N25Z4,1845
64
65
  luna_sdk/schemas/qpu_token.py,sha256=CFKbAhFgo0G-LO_lameHH4-iOFUJWx9hmMWi3xQwURw,1508
66
+ luna_sdk/schemas/qpu_token_time_quota.py,sha256=tIlYU2i43m93BOaCUrv62baY3RSIScWBqbD0BBlwES4,656
65
67
  luna_sdk/schemas/representation.py,sha256=0RKVV0XxHOJZ1o9grxTq5ri3cGLziyCFObDwQuXIOEY,364
66
68
  luna_sdk/schemas/rest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
69
  luna_sdk/schemas/rest/qpu_token/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
70
  luna_sdk/schemas/rest/qpu_token/qpu_token_source.py,sha256=EPMXHpgxqsQ4uJ1hlwe5gPdSsjuHEuKKAIMtBFgPJ1A,583
69
71
  luna_sdk/schemas/rest/qpu_token/token_provider.py,sha256=3Gecn2AmN7E_wAPUac_c55Fg-LwdDKsgbwAN2-0msJU,2985
70
- luna_sdk/schemas/solution.py,sha256=IRtZneNRN5IbSEMHKHc0NYJ7lf74RxZTHoYJI7z2QoY,6871
72
+ luna_sdk/schemas/solution.py,sha256=bNgd0UpsaQM_TrgTB-CJJiXuTg1ubMJP33y813yd5WY,8818
71
73
  luna_sdk/schemas/solver_info.py,sha256=ZUCdTI8zpPZ8EquLYyrLU35pZ4VkzcPUSYeQWkdijHM,799
72
74
  luna_sdk/schemas/solver_parameters/aws/__init__.py,sha256=CXjKWzgnP_d1_RvQUfWyaaWvsZ1FxLJN5K61QmRa-uw,33
73
75
  luna_sdk/schemas/solver_parameters/aws/optimizer_params.py,sha256=w0eg1SnTpKnuq48YG8JAC1LY0bxsTlZIJ2XbT2ySTHw,1374
74
76
  luna_sdk/schemas/solver_parameters/aws/qaoa.py,sha256=Mc7zfdWgLxh2Kb0r5OmL3RIkYlB1mnu6jUpmfYG2BBg,2290
75
77
  luna_sdk/schemas/solver_parameters/base_parameter.py,sha256=v8nk1aVKW_MaePxxNXXb3hcVDtzkQF1sGlvZ2YXXJVI,123
76
78
  luna_sdk/schemas/solver_parameters/dwave/__init__.py,sha256=yHsBQ5d1mCS90Y1JcTCOPjNCrEiGT23wI9GyPnYlIqo,2453
77
- luna_sdk/schemas/solver_parameters/dwave/base.py,sha256=PpPF49uT8XWzK-kRpkszYeFdFbksWkEDBqimq38-mzc,17281
79
+ luna_sdk/schemas/solver_parameters/dwave/base.py,sha256=z3zWZQAqDJU5dVY5sYTMe8Sxq92SIjhWlfBAmbsowE4,17364
78
80
  luna_sdk/schemas/solver_parameters/dwave/dialectic_search.py,sha256=CnXg7rcZ7mHkbSLrYXPot3-73YiWTRhkhyRmjZ_pvvs,1205
79
81
  luna_sdk/schemas/solver_parameters/dwave/kerberos.py,sha256=OPzCgo9h5845R3Sg_TrSkwp4gjoRKEHxhAhSdcJxY6c,2674
80
82
  luna_sdk/schemas/solver_parameters/dwave/leap_hybrid_bqm.py,sha256=foPfMJLQ0enO3omknKuqIxfZTXd9oIbfi_e-N0o2tmM,637
@@ -87,12 +89,12 @@ luna_sdk/schemas/solver_parameters/dwave/qaga.py,sha256=gVucZ_1feFb7aKl6W2m34_Hx
87
89
  luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_qpu.py,sha256=d72lNLdtD-G6WtVGwqmCse9r_O3inDAbLc6tbDlyu-Y,554
88
90
  luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_simulated_annealing.py,sha256=wo5Gt6A-N7APE2Nhz_eOhxmW7P_IYTzvdDKe-4kIMn4,976
89
91
  luna_sdk/schemas/solver_parameters/dwave/qbsolv_like_tabu_search.py,sha256=5r5piwo5BsAAlXmyqYMxXZDvgVTvjdJ2hVMr7-7h_lk,840
90
- luna_sdk/schemas/solver_parameters/dwave/quantum_annealing.py,sha256=h7HXAV67hdcsB0v00AcGNoMtb3pGjyjTG2HY-u3rsHg,631
91
- luna_sdk/schemas/solver_parameters/dwave/repeated_reverse_quantum_annealing.py,sha256=9QTkdgSesWVIfGo31uNMM0Xo-qIuL8XcmIOHlT4MzJU,3771
92
+ luna_sdk/schemas/solver_parameters/dwave/quantum_annealing.py,sha256=V00ZV2XMaYv9TZSezFm36kDUgiHpwBKG6K2t38ebgvY,1008
93
+ luna_sdk/schemas/solver_parameters/dwave/repeated_reverse_quantum_annealing.py,sha256=Y04GIwLAergf-6QXSsdZzdhuxYPsSwTf0Np9ahCwUTQ,4117
92
94
  luna_sdk/schemas/solver_parameters/dwave/repeated_reverse_simulated_annealing.py,sha256=UeLr2MnPS3zTBQgH6eq5hYvPJpOjQjqG-shHuQ8Ct0M,4569
93
95
  luna_sdk/schemas/solver_parameters/dwave/saga.py,sha256=pXWGZVXRgSMJRi3-NuyO7moai198cWXeGbvq5We-1EE,3118
94
96
  luna_sdk/schemas/solver_parameters/dwave/simulated_annealing.py,sha256=cU2UoN8xo3iM34LJhaLc-tYsCo-RqpOstiktEi79QRU,4047
95
- luna_sdk/schemas/solver_parameters/dwave/tabu_search.py,sha256=fqLoUcBT_CVBq8nmY-KGO_wBmVpAgUSSoS8N_tAOZ6E,3979
97
+ luna_sdk/schemas/solver_parameters/dwave/tabu_search.py,sha256=M027TrynHGPFWuzXcBwVaJz3J-Qf38k5poQRVqi7jLw,3885
96
98
  luna_sdk/schemas/solver_parameters/fujitsu/__init__.py,sha256=V4CSTiNSmtBvNuQpxiTZqX9T-oV4M8hZGQ_eO5Ro8vU,549
97
99
  luna_sdk/schemas/solver_parameters/fujitsu/base.py,sha256=yDM2sLBtg-a5OsD3GqwTd-HMmIwJtubbP_QxQcrkDnA,1813
98
100
  luna_sdk/schemas/solver_parameters/fujitsu/digital_annealer_cpu.py,sha256=EBPE7mwtUNs5CmyVkdWV9jQT_YnW8FWsYQ0VyCHBVNM,9747
@@ -160,7 +162,7 @@ luna_sdk/schemas/wrappers/datetime_wrapper.py,sha256=6usmPJNRYA4Fe_-0NGwe7RYams4
160
162
  luna_sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
161
163
  luna_sdk/utils/parameter_finder.py,sha256=LKkd1upH3Djd6eqkcSQ2feNwPUiKi8soYkx6JT1_VSg,2937
162
164
  luna_sdk/utils/qpu_tokens.py,sha256=xrh5KSoWzbul-6eRa0ELH9iwEENanE7PIms7jlCt3NY,1641
163
- luna_quantum-0.0.33.dist-info/LICENSE,sha256=rwwuFPLz36oRvjWu2oEeX42Qtn9gmbh7zRC2OqCFNaI,11342
164
- luna_quantum-0.0.33.dist-info/METADATA,sha256=5ojTfod6BKHtIKnRn_utUm3CVd9OifvhK8Lk2xqhD8o,2311
165
- luna_quantum-0.0.33.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
166
- luna_quantum-0.0.33.dist-info/RECORD,,
165
+ luna_quantum-0.10.1.dist-info/LICENSE,sha256=rwwuFPLz36oRvjWu2oEeX42Qtn9gmbh7zRC2OqCFNaI,11342
166
+ luna_quantum-0.10.1.dist-info/METADATA,sha256=BD5AD8c3uY615XODFmYbFvnf9_WsLt4P_e5K457-KsM,2311
167
+ luna_quantum-0.10.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
168
+ luna_quantum-0.10.1.dist-info/RECORD,,
@@ -1,6 +1,6 @@
1
1
  import os
2
2
  from enum import Enum
3
- from typing import Optional, Literal
3
+ from typing import Literal, Optional
4
4
 
5
5
  import httpx
6
6
 
@@ -1,6 +0,0 @@
1
- class EncryptionNotSetException(Exception):
2
- def __str__(self):
3
- return (
4
- "Encryption not set. Please refer to our encryption documentation "
5
- "https://docs.aqarios.com/get-started#luna-encryption for more information."
6
- )
@@ -15,7 +15,6 @@ class ICircuitRepo(IRepository, ABC):
15
15
  provider: CircuitProviderEnum,
16
16
  params: Dict[str, Any] = {},
17
17
  qpu_tokens: Optional[TokenProvider] = None,
18
- encryption_key: Optional[str] = None,
19
18
  **kwargs,
20
19
  ) -> CircuitJob:
21
20
  """
@@ -31,8 +30,6 @@ class ICircuitRepo(IRepository, ABC):
31
30
  Additional parameters of the circuit.
32
31
  qpu_tokens: Optional[TokenProvider]
33
32
  The tokens to be used for the QPU.
34
- encryption_key: Optional[str]
35
- Encryption key to be used for encryption of QPU tokens.
36
33
  **kwargs
37
34
  Parameters to pass to `httpx.request`.
38
35
 
@@ -47,7 +44,6 @@ class ICircuitRepo(IRepository, ABC):
47
44
  def get(
48
45
  self,
49
46
  job: CircuitJob,
50
- encryption_key: Optional[str] = None,
51
47
  **kwargs,
52
48
  ) -> CircuitResult:
53
49
  """
@@ -55,8 +51,6 @@ class ICircuitRepo(IRepository, ABC):
55
51
 
56
52
  Parameters
57
53
  ----------
58
- encryption_key: Optional[str]
59
- Encryption key to be used for encryption of QPU tokens.
60
54
  **kwargs
61
55
  Parameters to pass to `httpx.request`.
62
56
 
@@ -1,9 +1,11 @@
1
1
  from abc import ABC, abstractmethod
2
+ from datetime import datetime
2
3
  from typing import Dict, List, Optional
3
4
 
4
5
  from luna_sdk.interfaces.repository_i import IRepository
5
6
  from luna_sdk.schemas import QpuTokenOut
6
7
  from luna_sdk.schemas.enums.qpu_token_type import QpuTokenTypeEnum
8
+ from luna_sdk.schemas.qpu_token_time_quota import QpuTokenTimeQuotaOut
7
9
 
8
10
 
9
11
  class IQpuTokenRepo(IRepository, ABC):
@@ -14,7 +16,6 @@ class IQpuTokenRepo(IRepository, ABC):
14
16
  provider: str,
15
17
  token: str,
16
18
  token_type: QpuTokenTypeEnum,
17
- encryption_key: Optional[str] = None,
18
19
  **kwargs,
19
20
  ) -> QpuTokenOut:
20
21
  """
@@ -32,8 +33,6 @@ class IQpuTokenRepo(IRepository, ABC):
32
33
  There are two types of QPU tokens: PERSONAL and GROUP.
33
34
  All users of a group can use group QPU tokens.
34
35
  User QPU tokens can only be used by the user who created them.
35
- encryption_key: Optional[str]
36
- Encryption key to be used for encryption of QPU tokens.
37
36
  **kwargs
38
37
  Parameters to pass to `httpx.request`.
39
38
 
@@ -48,7 +47,6 @@ class IQpuTokenRepo(IRepository, ABC):
48
47
  def get_all(
49
48
  self,
50
49
  filter_provider: Optional[str] = None,
51
- name: Optional[str] = None,
52
50
  token_type: Optional[QpuTokenTypeEnum] = None,
53
51
  limit: Optional[int] = None,
54
52
  offset: Optional[int] = None,
@@ -61,8 +59,6 @@ class IQpuTokenRepo(IRepository, ABC):
61
59
  ----------
62
60
  filter_provider: Optional[str]
63
61
  The provider for which qpu tokens should be retrieved
64
- name: Optional[str]
65
- Name of the QPU token that should be retrieved
66
62
  token_type: Optional[QpuTokenTypeEnum]
67
63
  If you want to retrieve only user or group QPU tokens
68
64
  otherwise all QPU tokens will be retrieved
@@ -151,3 +147,201 @@ class IQpuTokenRepo(IRepository, ABC):
151
147
  Parameters to pass to `httpx.request`.
152
148
  """
153
149
  raise NotImplementedError
150
+
151
+ @abstractmethod
152
+ def create_group_time_quota(
153
+ self,
154
+ qpu_token_name: str,
155
+ quota: int,
156
+ start: Optional[datetime] = None,
157
+ end: Optional[datetime] = None,
158
+ **kwargs,
159
+ ) -> None:
160
+ """Create a time quota policy for a shared QPU token that affects every user of
161
+ the group.
162
+
163
+ Parameters
164
+ ----------
165
+ qpu_token_name : str
166
+ The name of the qpu token. Currently, only DWave tokens are supported.
167
+ quota : int
168
+ quota : int
169
+ The amount of quota to add. For DWave Quantum Annealing, which is currently
170
+ the only algorithm that supports time quota, this is the qpu access time in
171
+ nanoseconds.
172
+ start : Optional[datetime], optional
173
+ The date and time from which the policy is active. If None, the current date
174
+ and time will be used. If the policy is currently not effective, the token
175
+ cannot be used at all.
176
+ Default: None
177
+ end : Optional[datetime], optional
178
+ The date and time until which the policy is active. If None, the policy if
179
+ effective until 265 days after the start date. If the policy is currently
180
+ not effective, the token cannot be used at all.
181
+ Default: None
182
+ """
183
+ raise NotImplementedError
184
+
185
+ @abstractmethod
186
+ def get_group_time_quota(
187
+ self, qpu_token_name: str, **kwargs
188
+ ) -> Optional[QpuTokenTimeQuotaOut]:
189
+ """Get the group time quota policy for a qpu token.
190
+
191
+ Parameters
192
+ ----------
193
+ qpu_token_name : str
194
+ The name of the qpu token.
195
+
196
+ Returns
197
+ -------
198
+ Optional[QpuTokenTimeQuotaOut]
199
+ The token policy. None, if no group policy is set on this token.
200
+ """
201
+ raise NotImplementedError
202
+
203
+ @abstractmethod
204
+ def update_group_time_quota(
205
+ self,
206
+ qpu_token_name: str,
207
+ quota: Optional[int] = None,
208
+ start: Optional[datetime] = None,
209
+ end: Optional[datetime] = None,
210
+ **kwargs,
211
+ ) -> None:
212
+ """Update the details on a group qpu time quota policy.
213
+
214
+ Parameters
215
+ ----------
216
+ qpu_token_name : str
217
+ The name of the qpu token.
218
+ quota : Optional[int], optional
219
+ The amount of quota. For DWave Quantum Annealing, which is currently the
220
+ only supported solver, this is the qpu access time in nanoseconds. If None,
221
+ the available quota won't be updated.
222
+ Default: None
223
+ start : Optional[datetime], optional
224
+ The date and time from which the policy is active. If None, the start date
225
+ won't be updated.
226
+ Default: None
227
+ end : Optional[datetime], optional
228
+ The date and time until which the policy is active. If None, the end date
229
+ won't be updated.
230
+ Default: None
231
+ """
232
+ raise NotImplementedError
233
+
234
+ @abstractmethod
235
+ def delete_group_time_quota(self, qpu_token_name: str, **kwargs) -> None:
236
+ """Delete the group policy set on a qpu token.
237
+
238
+ Parameters
239
+ ----------
240
+ qpu_token_name : str
241
+ The name of the qpu token.
242
+ """
243
+ raise NotImplementedError
244
+
245
+ @abstractmethod
246
+ def create_user_time_quota(
247
+ self,
248
+ qpu_token_name: str,
249
+ user_email: str,
250
+ quota: int,
251
+ start: Optional[datetime] = None,
252
+ end: Optional[datetime] = None,
253
+ **kwargs,
254
+ ) -> None:
255
+ """Create a time quota policy for a shared QPU token that affects a single user
256
+ of the group.
257
+
258
+ Parameters
259
+ ----------
260
+ qpu_token_name : str
261
+ The name of the qpu token. Currently, only DWave tokens are supported.
262
+ user_email : str
263
+ Email of the user for whom to add the policy.
264
+ quota : int
265
+ The amount of quota to add. For DWave Quantum Annealing, which is currently
266
+ the only algorithm that supports time quota, this is the qpu access time in
267
+ nanoseconds.
268
+ start : Optional[datetime], optional
269
+ The date and time from which the policy is active. If None, the current date
270
+ and time will be used. If the policy is currently not effective, the token
271
+ cannot be used at all.
272
+ Default: None
273
+ end : Optional[datetime], optional
274
+ The date and time until which the policy is active. If None, the policy if
275
+ effective until 265 days after the start date. If the policy is currently
276
+ not effective, the token cannot be used at all.
277
+ Default: None
278
+ """
279
+ raise NotImplementedError
280
+
281
+ @abstractmethod
282
+ def get_user_time_quota(
283
+ self, qpu_token_name: str, user_email: str, **kwargs
284
+ ) -> Optional[QpuTokenTimeQuotaOut]:
285
+ """Get a user-specific time quota policy for a qpu token.
286
+
287
+ Parameters
288
+ ----------
289
+ qpu_token_name : str
290
+ The name of the qpu token.
291
+ user_email : str
292
+ Email of the user for whom to get the policy.
293
+
294
+ Returns
295
+ -------
296
+ Optional[QpuTokenTimeQuotaOut]
297
+ The token policy. None, if no policy is set on this token for the specified
298
+ user.
299
+ """
300
+ raise NotImplementedError
301
+
302
+ @abstractmethod
303
+ def update_user_time_quota(
304
+ self,
305
+ qpu_token_name: str,
306
+ user_email: str,
307
+ quota: Optional[int] = None,
308
+ start: Optional[datetime] = None,
309
+ end: Optional[datetime] = None,
310
+ **kwargs,
311
+ ) -> None:
312
+ """Update the details on a user-specific qpu time quota policy.
313
+
314
+ Parameters
315
+ ----------
316
+ qpu_token_name : str
317
+ The name of the qpu token.
318
+ user_email : str
319
+ Email of the user for whom to update the policy.
320
+ quota : Optional[int], optional
321
+ The amount of quota. For DWave Quantum Annealing, which is currently the
322
+ only supported solver, this is the qpu access time in nanoseconds. If None,
323
+ the available quota won't be updated.
324
+ Default: None
325
+ start : Optional[datetime], optional
326
+ The date and time from which the policy is active. If None, the start date
327
+ won't be updated.
328
+ Default: None
329
+ end : Optional[datetime], optional
330
+ The date and time until which the policy is active. If None, the end date
331
+ won't be updated.
332
+ Default: None
333
+ """
334
+ raise NotImplementedError
335
+
336
+ @abstractmethod
337
+ def delete_user_time_quota(
338
+ self, qpu_token_name: str, user_email: str, **kwargs
339
+ ) -> None:
340
+ """Delete a user-specific policy set on a qpu token.
341
+
342
+ Parameters
343
+ ----------
344
+ qpu_token_name : str
345
+ The name of the qpu token.
346
+ """
347
+ raise NotImplementedError
@@ -108,7 +108,6 @@ class ISolutionsRepo(IRepository, ABC):
108
108
  provider: str,
109
109
  qpu_tokens: Optional[TokenProvider] = None,
110
110
  solver_parameters: Optional[Union[Dict[str, Any], BaseModel]] = None,
111
- encryption_key: Optional[str] = None,
112
111
  name: Optional[str] = None,
113
112
  fail_on_invalid_params: bool = True,
114
113
  **kwargs,
@@ -128,8 +127,6 @@ class ISolutionsRepo(IRepository, ABC):
128
127
  The tokens to be used for the QPU.
129
128
  solver_parameters: Optional[Union[Dict[str, Any], BaseModel]]
130
129
  Parameters to be passed to the solver.
131
- encryption_key: Optional[str]
132
- Encryption key to be used for encryption of QPU tokens.
133
130
  name: Optional[str]
134
131
  Default: None, The name of the solution to create.
135
132
  fail_on_invalid_params: bool
@@ -155,7 +152,6 @@ class ISolutionsRepo(IRepository, ABC):
155
152
  sleep_time_max: float = 60.0,
156
153
  sleep_time_increment: float = 5.0,
157
154
  sleep_time_initial: float = 5.0,
158
- encryption_key: Optional[str] = None,
159
155
  name: Optional[str] = None,
160
156
  fail_on_invalid_params: bool = True,
161
157
  **kwargs,
@@ -182,8 +178,6 @@ class ISolutionsRepo(IRepository, ABC):
182
178
  Increment of sleep time between requests. Initial sleep time will be
183
179
  sleep_time_initial: float
184
180
  Initial sleep time.
185
- encryption_key: Optional[str]
186
- Encryption key to be used for encryption of QPU tokens.
187
181
  name: Optional[str]
188
182
  Default: None, The name of the solution to create.
189
183
  fail_on_invalid_params: bool
@@ -237,3 +231,26 @@ class ISolutionsRepo(IRepository, ABC):
237
231
  not (yet) available or the solution sense is `None`, `None` is returned.
238
232
  """
239
233
  raise NotImplementedError
234
+
235
+ @abstractmethod
236
+ def cancel(
237
+ self,
238
+ solution_id: str,
239
+ **kwargs,
240
+ ) -> Solution:
241
+ """
242
+ Cancel a solve job for an optimization.
243
+
244
+ Parameters
245
+ ----------
246
+ solution_id: str
247
+ The id of the solution which should be canceled.
248
+ **kwargs
249
+ Parameters to pass to `httpx.request`.
250
+
251
+ Returns
252
+ -------
253
+ SolutionOut
254
+ The location where the solution can be found once solving is complete.
255
+ """
256
+ raise NotImplementedError
@@ -1,7 +1,6 @@
1
1
  import os
2
2
  from typing import Any, Dict, Optional
3
3
 
4
- from luna_sdk.exceptions.encryption_exception import EncryptionNotSetException
5
4
  from luna_sdk.interfaces.circuit_repo_i import ICircuitRepo
6
5
  from luna_sdk.schemas.circuit import CircuitJob, CircuitResult
7
6
  from luna_sdk.schemas.create.circuit import CircuitIn
@@ -20,7 +19,6 @@ class CircuitRepo(ICircuitRepo):
20
19
  provider: CircuitProviderEnum,
21
20
  params: Dict[str, Any] = {},
22
21
  qpu_tokens: Optional[TokenProvider] = None,
23
- encryption_key: Optional[str] = None,
24
22
  **kwargs,
25
23
  ) -> CircuitJob:
26
24
  if qpu_tokens is not None:
@@ -34,15 +32,11 @@ class CircuitRepo(ICircuitRepo):
34
32
  if rest_qpu_tokens is None:
35
33
  rest_qpu_tokens = extract_qpu_tokens_from_env()
36
34
 
37
- encryption_key = encryption_key or os.environ.get("LUNA_ENCRYPTION_KEY")
38
- if encryption_key is None:
39
- raise EncryptionNotSetException
40
35
  circuit_in: CircuitIn = CircuitIn(
41
36
  provider=provider,
42
37
  circuit=circuit,
43
38
  params=params,
44
39
  qpu_tokens=rest_qpu_tokens,
45
- encryption_key=encryption_key,
46
40
  )
47
41
 
48
42
  response = self._client.post(
@@ -55,16 +49,11 @@ class CircuitRepo(ICircuitRepo):
55
49
  def get(
56
50
  self,
57
51
  job: CircuitJob,
58
- encryption_key: Optional[str] = None,
59
52
  **kwargs,
60
53
  ) -> CircuitResult:
61
54
  url = f"{self._endpoint}/{job.id}/{job.provider.value}"
62
- encryption_key = encryption_key or os.environ.get("LUNA_ENCRYPTION_KEY")
63
- if encryption_key is None:
64
- raise EncryptionNotSetException
65
55
  if job.params is None:
66
56
  job.params = {}
67
- job.params["encryption_key"] = encryption_key
68
57
  response = self._client.get(url, params=job.params, **kwargs)
69
58
 
70
59
  response.raise_for_status()
@@ -1,14 +1,18 @@
1
1
  import json
2
- import os
2
+ from datetime import datetime
3
3
  from typing import Dict, List, Optional
4
4
 
5
5
  from httpx import Response
6
+ from pydantic import TypeAdapter
6
7
 
7
- from luna_sdk.exceptions.encryption_exception import EncryptionNotSetException
8
8
  from luna_sdk.interfaces.qpu_token_repo_i import IQpuTokenRepo
9
9
  from luna_sdk.schemas import QpuTokenOut
10
- from luna_sdk.schemas.create import QpuTokenIn
10
+ from luna_sdk.schemas.create import QpuTokenIn, QpuTokenTimeQuotaIn
11
11
  from luna_sdk.schemas.enums.qpu_token_type import QpuTokenTypeEnum
12
+ from luna_sdk.schemas.qpu_token_time_quota import QpuTokenTimeQuotaOut
13
+
14
+ _ORGANIZATION_QPU_TOKENS_BACKEND = "shared"
15
+ _PERSONAL_QPU_TOKENS_BACKEND = "private"
12
16
 
13
17
 
14
18
  class QpuTokenRepo(IQpuTokenRepo):
@@ -22,9 +26,9 @@ class QpuTokenRepo(IQpuTokenRepo):
22
26
  if token_type is None:
23
27
  return f"{self._endpoint}"
24
28
  elif token_type == QpuTokenTypeEnum.PERSONAL:
25
- return f"{self._endpoint}/private"
29
+ return f"{self._endpoint}/{_PERSONAL_QPU_TOKENS_BACKEND}"
26
30
  else:
27
- return f"{self._endpoint}/shared"
31
+ return f"{self._endpoint}/{_ORGANIZATION_QPU_TOKENS_BACKEND}"
28
32
 
29
33
  def _get_by_name(
30
34
  self, name: str, token_type: QpuTokenTypeEnum, **kwargs
@@ -44,17 +48,12 @@ class QpuTokenRepo(IQpuTokenRepo):
44
48
  provider: str,
45
49
  token: str,
46
50
  token_type: QpuTokenTypeEnum,
47
- encryption_key: Optional[str] = None,
48
51
  **kwargs,
49
52
  ) -> QpuTokenOut:
50
- encryption_key = encryption_key or os.environ.get("LUNA_ENCRYPTION_KEY")
51
- if encryption_key is None:
52
- raise EncryptionNotSetException
53
53
  qpu_token = QpuTokenIn(
54
54
  name=name,
55
55
  provider=provider,
56
56
  token=token,
57
- encryption_key=encryption_key,
58
57
  )
59
58
 
60
59
  response: Response = self._client.post(
@@ -70,7 +69,6 @@ class QpuTokenRepo(IQpuTokenRepo):
70
69
  def get_all(
71
70
  self,
72
71
  filter_provider: Optional[str] = None,
73
- name: Optional[str] = None,
74
72
  token_type: Optional[QpuTokenTypeEnum] = None,
75
73
  limit: Optional[int] = None,
76
74
  offset: Optional[int] = None,
@@ -80,38 +78,33 @@ class QpuTokenRepo(IQpuTokenRepo):
80
78
  if filter_provider:
81
79
  params["filter_provider"] = filter_provider
82
80
 
83
- if name:
84
- params["name"] = name
85
81
  if limit is not None:
86
82
  params["limit"] = str(limit)
87
83
  if offset is not None:
88
84
  params["offset"] = str(offset)
85
+ if token_type == QpuTokenTypeEnum.PERSONAL:
86
+ params["token_type"] = _PERSONAL_QPU_TOKENS_BACKEND
87
+ if token_type == QpuTokenTypeEnum.GROUP:
88
+ params["token_type"] = _ORGANIZATION_QPU_TOKENS_BACKEND
89
89
 
90
+ response = self._client.get(
91
+ self._endpoint,
92
+ params=params,
93
+ **kwargs,
94
+ )
95
+ ta = TypeAdapter(List[QpuTokenOut])
90
96
  to_return: Dict[QpuTokenTypeEnum, List[QpuTokenOut]] = {}
91
- if token_type is None or token_type == QpuTokenTypeEnum.PERSONAL:
92
- response = self._client.get(
93
- self._get_endpoint_by_type(QpuTokenTypeEnum.PERSONAL),
94
- params=params,
95
- **kwargs,
96
- )
97
- response.raise_for_status()
98
- personal_qpu_tokens = response.json()
99
- to_return[QpuTokenTypeEnum.PERSONAL] = [
100
- QpuTokenOut(**qpu_token, token_type=QpuTokenTypeEnum.PERSONAL)
101
- for qpu_token in personal_qpu_tokens
102
- ]
103
- if token_type is None or token_type == QpuTokenTypeEnum.GROUP:
104
- response = self._client.get(
105
- self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP),
106
- params=params,
107
- **kwargs,
108
- )
109
- response.raise_for_status()
110
- shared_qpu_tokens = response.json()
111
- to_return[QpuTokenTypeEnum.GROUP] = [
112
- QpuTokenOut(**qpu_token, token_type=QpuTokenTypeEnum.GROUP)
113
- for qpu_token in shared_qpu_tokens
114
- ]
97
+ resp = response.json()
98
+
99
+ shared_tokens = resp.get(_ORGANIZATION_QPU_TOKENS_BACKEND, [])
100
+ for qpu_token in shared_tokens:
101
+ qpu_token["token_type"] = QpuTokenTypeEnum.GROUP
102
+ to_return[QpuTokenTypeEnum.GROUP] = ta.validate_python(shared_tokens)
103
+
104
+ personal_tokens = resp.get(_PERSONAL_QPU_TOKENS_BACKEND, [])
105
+ for qpu_token in personal_tokens:
106
+ qpu_token["token_type"] = QpuTokenTypeEnum.PERSONAL
107
+ to_return[QpuTokenTypeEnum.PERSONAL] = ta.validate_python(personal_tokens)
115
108
 
116
109
  return to_return
117
110
 
@@ -148,3 +141,125 @@ class QpuTokenRepo(IQpuTokenRepo):
148
141
  f"{self._get_endpoint_by_type(token_type)}/{name}", **kwargs
149
142
  )
150
143
  response.raise_for_status()
144
+
145
+ def create_group_time_quota(
146
+ self,
147
+ qpu_token_name: str,
148
+ quota: int,
149
+ start: Optional[datetime] = None,
150
+ end: Optional[datetime] = None,
151
+ **kwargs,
152
+ ) -> None:
153
+ time_quota = QpuTokenTimeQuotaIn(quota=quota, start=start, end=end)
154
+
155
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
156
+ response = self._client.post(
157
+ f"{endpoint}/quota/group/{qpu_token_name}",
158
+ content=time_quota.model_dump_json(),
159
+ **kwargs,
160
+ )
161
+ response.raise_for_status()
162
+
163
+ def get_group_time_quota(
164
+ self, qpu_token_name: str, **kwargs
165
+ ) -> Optional[QpuTokenTimeQuotaOut]:
166
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
167
+ response = self._client.get(
168
+ f"{endpoint}/quota/group/{qpu_token_name}", **kwargs
169
+ )
170
+ response.raise_for_status()
171
+
172
+ time_quota_data = response.json()
173
+
174
+ if time_quota_data is None:
175
+ return None
176
+ return QpuTokenTimeQuotaOut.model_validate(time_quota_data)
177
+
178
+ def update_group_time_quota(
179
+ self,
180
+ qpu_token_name: str,
181
+ quota: Optional[int] = None,
182
+ start: Optional[datetime] = None,
183
+ end: Optional[datetime] = None,
184
+ **kwargs,
185
+ ) -> None:
186
+ data = {"quota": quota, "start": start, "end": end}
187
+
188
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
189
+ response = self._client.patch(
190
+ f"{endpoint}/quota/group/{qpu_token_name}",
191
+ content=json.dumps(data),
192
+ **kwargs,
193
+ )
194
+ response.raise_for_status()
195
+
196
+ def delete_group_time_quota(self, qpu_token_name: str, **kwargs) -> None:
197
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
198
+ response = self._client.delete(
199
+ f"{endpoint}/quota/group/{qpu_token_name}",
200
+ **kwargs,
201
+ )
202
+ response.raise_for_status()
203
+
204
+ def create_user_time_quota(
205
+ self,
206
+ qpu_token_name: str,
207
+ user_email: str,
208
+ quota: int,
209
+ start: Optional[datetime] = None,
210
+ end: Optional[datetime] = None,
211
+ **kwargs,
212
+ ) -> None:
213
+ time_quota = QpuTokenTimeQuotaIn(quota=quota, start=start, end=end)
214
+
215
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
216
+ response = self._client.post(
217
+ f"{endpoint}/quota/user/{qpu_token_name}/{user_email}",
218
+ content=time_quota.model_dump_json(),
219
+ **kwargs,
220
+ )
221
+ response.raise_for_status()
222
+
223
+ def get_user_time_quota(
224
+ self, qpu_token_name: str, user_email: str, **kwargs
225
+ ) -> Optional[QpuTokenTimeQuotaOut]:
226
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
227
+ response = self._client.get(
228
+ f"{endpoint}/quota/user/{qpu_token_name}/{user_email}", **kwargs
229
+ )
230
+ response.raise_for_status()
231
+
232
+ time_quota_data = response.json()
233
+
234
+ if time_quota_data is None:
235
+ return None
236
+ return QpuTokenTimeQuotaOut.model_validate(time_quota_data)
237
+
238
+ def update_user_time_quota(
239
+ self,
240
+ qpu_token_name: str,
241
+ user_email: str,
242
+ quota: Optional[int] = None,
243
+ start: Optional[datetime] = None,
244
+ end: Optional[datetime] = None,
245
+ **kwargs,
246
+ ) -> None:
247
+ data = {"quota": quota, "start": start, "end": end}
248
+
249
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
250
+ response = self._client.patch(
251
+ f"{endpoint}/quota/user/{qpu_token_name}/{user_email}",
252
+ content=json.dumps(data),
253
+ **kwargs,
254
+ )
255
+ response.raise_for_status()
256
+
257
+ def delete_user_time_quota(
258
+ self, qpu_token_name: str, user_email: str, **kwargs
259
+ ) -> None:
260
+ endpoint = self._get_endpoint_by_type(QpuTokenTypeEnum.GROUP)
261
+ response = self._client.delete(
262
+ f"{endpoint}/quota/user/{qpu_token_name}/{user_email}",
263
+ **kwargs,
264
+ )
265
+ response.raise_for_status()
@@ -5,7 +5,6 @@ from typing import Any, Dict, List, Optional, Type, Union
5
5
 
6
6
  from pydantic import BaseModel, ValidationError
7
7
 
8
- from luna_sdk.exceptions.encryption_exception import EncryptionNotSetException
9
8
  from luna_sdk.interfaces.solutions_repo_i import ISolutionsRepo
10
9
  from luna_sdk.schemas.create.solution import SolutionIn
11
10
  from luna_sdk.schemas.enums.solution import SenseEnum
@@ -70,7 +69,6 @@ class SolutionsRepo(ISolutionsRepo):
70
69
  provider: str,
71
70
  qpu_tokens: Optional[TokenProvider] = None,
72
71
  solver_parameters: Optional[Union[Dict[str, Any], BaseModel]] = None,
73
- encryption_key: Optional[str] = None,
74
72
  name: Optional[str] = None,
75
73
  fail_on_invalid_params: bool = True,
76
74
  **kwargs,
@@ -85,9 +83,6 @@ class SolutionsRepo(ISolutionsRepo):
85
83
  if rest_qpu_tokens is None:
86
84
  rest_qpu_tokens = extract_qpu_tokens_from_env()
87
85
 
88
- encryption_key = encryption_key or os.environ.get("LUNA_ENCRYPTION_KEY")
89
- if encryption_key is None:
90
- raise EncryptionNotSetException
91
86
  params = SolutionsRepo.validate_solver_params(
92
87
  solver_name, provider, solver_parameters, fail_on_invalid_params
93
88
  )
@@ -98,7 +93,6 @@ class SolutionsRepo(ISolutionsRepo):
98
93
  provider=provider,
99
94
  parameters=params,
100
95
  qpu_tokens=rest_qpu_tokens,
101
- encryption_key=encryption_key,
102
96
  name=name,
103
97
  )
104
98
  response = self._client.post(
@@ -118,7 +112,6 @@ class SolutionsRepo(ISolutionsRepo):
118
112
  sleep_time_max: float = 60.0,
119
113
  sleep_time_increment: float = 5.0,
120
114
  sleep_time_initial: float = 5.0,
121
- encryption_key: Optional[str] = None,
122
115
  name: Optional[str] = None,
123
116
  fail_on_invalid_params: bool = True,
124
117
  **kwargs,
@@ -134,7 +127,6 @@ class SolutionsRepo(ISolutionsRepo):
134
127
  provider=provider,
135
128
  solver_parameters=params,
136
129
  qpu_tokens=qpu_tokens,
137
- encryption_key=encryption_key,
138
130
  name=name,
139
131
  **kwargs,
140
132
  )
@@ -273,3 +265,9 @@ class SolutionsRepo(ISolutionsRepo):
273
265
  "Solving with Luna can still fail due to the parameters."
274
266
  )
275
267
  return params
268
+
269
+ def cancel(self, solution_id: str, **kwargs) -> Solution:
270
+ response = self._client.post(f"{self._endpoint}/{solution_id}/cancel", **kwargs)
271
+
272
+ response.raise_for_status()
273
+ return Solution.model_validate_json(response.text)
@@ -1,3 +1,4 @@
1
1
  from .circuit import CircuitIn
2
2
  from .qpu_token import QpuTokenIn
3
+ from .qpu_token_time_quota import QpuTokenTimeQuotaIn
3
4
  from .qubo import QUBOIn
@@ -18,12 +18,9 @@ class CircuitIn(BaseModel):
18
18
  The QASM circuit
19
19
  params: Dict[str, Any]
20
20
  Additional parameters
21
- encryption_key: str
22
- Encryption key to be used for encryption of QPU tokens.
23
21
  """
24
22
 
25
23
  provider: CircuitProviderEnum
26
24
  circuit: str
27
25
  params: Dict[str, Any] = {}
28
26
  qpu_tokens: Optional[RestAPITokenProvider] = None
29
- encryption_key: str
@@ -13,14 +13,11 @@ class QpuTokenIn(BaseModel):
13
13
  Name of provider
14
14
  token: str
15
15
  Token
16
- encryption_key: str
17
- Encryption key to be used for encryption of QPU tokens.
18
16
  """
19
17
 
20
18
  name: str
21
19
  provider: str
22
20
  token: str
23
- encryption_key: str
24
21
 
25
22
  class Config:
26
23
  extra = Extra.forbid
@@ -0,0 +1,25 @@
1
+ from datetime import datetime
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel
5
+
6
+
7
+ class QpuTokenTimeQuotaIn(BaseModel):
8
+ """
9
+ Pydantic model for creating a time quota on a qpu token.
10
+
11
+ Attributes
12
+ ----------
13
+ quota: int
14
+ The amount of quota.
15
+ start: datetime | None
16
+ Effective start date of the time quota policy.
17
+ If None, policy will be in effect immediately.
18
+ end: datetime | None
19
+ Effective end date of the time quota policy.
20
+ If None, policy will be in effect until 365 days after the start date.
21
+ """
22
+
23
+ quota: int
24
+ start: Optional[datetime]
25
+ end: Optional[datetime]
@@ -11,5 +11,4 @@ class SolutionIn(BaseModel):
11
11
  provider: str
12
12
  parameters: Dict[str, Any]
13
13
  qpu_tokens: Optional[RestAPITokenProvider] = None
14
- encryption_key: str
15
14
  name: Optional[str] = None
@@ -7,4 +7,5 @@ class StatusEnum(str, Enum):
7
7
  IN_PROGRESS = "IN_PROGRESS"
8
8
  DONE = "DONE"
9
9
  FAILED = "FAILED"
10
- CANCELLED = "CANCELED"
10
+ CANCELED = "CANCELED"
11
+ TIMEOUT = "TIMEOUT"
@@ -38,6 +38,50 @@ class Optimization(PrettyBase):
38
38
  use_case_name: Optional[str] = None
39
39
  params: Optional[Dict[str, Any]] = None
40
40
 
41
+ verbose: bool = False
42
+
43
+ def __str__(self):
44
+ if self.verbose:
45
+ return self.details()
46
+ return self.subset()
47
+
48
+ def details(self):
49
+ trimmed_keys = [
50
+ "verbose",
51
+ ]
52
+ data = self.model_dump()
53
+ output = ""
54
+ data_subset = {key: data[key] for key in data if key not in trimmed_keys}
55
+ ordered_subset = {
56
+ "id": data_subset.pop("id"),
57
+ "name": data_subset.pop("name"),
58
+ "original_format": data_subset.pop("original_format"),
59
+ "created_date": data_subset.pop("created_date"),
60
+ **data_subset,
61
+ }
62
+ output += self._pretty_print(ordered_subset)
63
+ return output
64
+
65
+ def subset(self):
66
+ trimmed_keys = [
67
+ "id",
68
+ "name",
69
+ "original_format",
70
+ "created_date",
71
+ ]
72
+ data = self.model_dump()
73
+ output = ""
74
+ data_subset = {key: data[key] for key in data if key in trimmed_keys}
75
+
76
+ ordered_subset = {
77
+ "id": data_subset.pop("id"),
78
+ "name": data_subset.pop("name"),
79
+ "original_format": data_subset.pop("original_format"),
80
+ **data_subset,
81
+ }
82
+ output += self._pretty_print(ordered_subset)
83
+ return output
84
+
41
85
  model_config = ConfigDict(extra="ignore", from_attributes=False)
42
86
 
43
87
 
@@ -0,0 +1,26 @@
1
+ from datetime import datetime
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class QpuTokenTimeQuotaOut(BaseModel):
7
+ """
8
+ Pydantic model for QPU token time quota OUT.
9
+ It contains the data received from the API call.
10
+
11
+ Attributes
12
+ ----------
13
+ quota: int
14
+ The total amount of quota available on a qpu token.
15
+ start: datetime
16
+ Effective start date of the time quota policy.
17
+ end: datetime
18
+ Effective end date of the time quota policy.
19
+ quota_used: int
20
+ How much quota has already been used from the totally available amount of quota.
21
+ """
22
+
23
+ quota: int
24
+ start: datetime
25
+ end: datetime
26
+ quota_used: int
@@ -1,7 +1,9 @@
1
+ from datetime import datetime
1
2
  from typing import Any, Dict, List, Optional, Union
2
3
 
3
4
  from pydantic import BaseModel
4
5
 
6
+ from luna_sdk.schemas.enums.optimization import OptFormat
5
7
  from luna_sdk.schemas.enums.solution import SenseEnum
6
8
  from luna_sdk.schemas.enums.status import StatusEnum
7
9
  from luna_sdk.schemas.optimization import Optimization
@@ -97,7 +99,7 @@ class Solution(PrettyBase):
97
99
  error_message: Optional[str] = None
98
100
  solver_job_info: Optional[str] = None
99
101
 
100
- results: Optional[List[Result]]
102
+ results: Optional[List[Result]] = None
101
103
  params: Dict[str, Any]
102
104
  runtime: Optional[Runtime]
103
105
  sense: Optional[SenseEnum]
@@ -105,45 +107,20 @@ class Solution(PrettyBase):
105
107
  solver: str
106
108
  provider: str
107
109
  status: StatusEnum
110
+ status_timeline: Dict[StatusEnum, datetime] = {}
111
+ used_format: Optional[OptFormat] = None
108
112
  optimization: Union[Optimization, str]
109
113
  representation: Optional[Any] = None
110
114
 
111
- def __str__(self):
112
- """Overwrite the default object string representation to use the custom pretty print console representation"""
113
- data = self.model_dump()
114
- results = data.pop("results") # Extract and remove results from data
115
- metadata = data.pop("metadata") # Extract and remove metadata from data
116
- provider = data["provider"]
117
-
118
- divider = "--------------------------------------------------------------------------------\n"
119
-
120
- # Build Meta Data section
121
- output = f"{divider}META DATA:\n{divider}"
122
- output += self._pretty_print(data)
123
-
124
- # Build Results section
125
- if results:
126
- output += f"\n\n{divider}RESULTS:\n{divider}"
127
- for i, result in enumerate(results, start=1):
128
- r = f"Result {i}:\n"
129
- r += f" {result}\n"
130
- output += r
131
- else:
132
- output += f"\n\n{divider}RESULTS:\n{divider}"
133
- output += " No results..\n"
134
- output += " Solution has status: " + str(self.status.value) + "\n"
135
- if self.error_message:
136
- output += " Error message: " + str(self.error_message) + "\n"
115
+ verbose: bool = False
137
116
 
138
- # Build Provider Meta Data section
139
- output += f"\n\n{divider}{provider.upper()} META DATA:\n{divider}"
140
- output += (
141
- self._pretty_print(metadata)
142
- if metadata
143
- else " No metadata from provider..\n"
144
- )
117
+ is_cancelable: bool = True
118
+ is_cancellation_requested: bool = False
145
119
 
146
- return output
120
+ def __str__(self):
121
+ if self.verbose:
122
+ return self.details()
123
+ return self.subset()
147
124
 
148
125
  @property
149
126
  def head(self):
@@ -216,6 +193,87 @@ class Solution(PrettyBase):
216
193
 
217
194
  return output
218
195
 
196
+ def details(self):
197
+ """Overwrite the default object string representation to use the custom pretty print console representation"""
198
+ data = self.model_dump()
199
+ results = data.pop("results") # Extract and remove results from data
200
+ metadata = data.pop("metadata") # Extract and remove metadata from data
201
+ provider = data["provider"]
202
+ data.pop("verbose") # Remove verbose field from data
203
+
204
+ divider = "--------------------------------------------------------------------------------\n"
205
+
206
+ # Build Meta Data section
207
+ output = f"{divider}META DATA:\n{divider}"
208
+ output += self._pretty_print(data)
209
+
210
+ # Build Results section
211
+ if results:
212
+ output += f"\n\n{divider}RESULTS:\n{divider}"
213
+ for i, result in enumerate(results, start=1):
214
+ r = f"Result {i}:\n"
215
+ r += f" {result}\n"
216
+ output += r
217
+ else:
218
+ output += f"\n\n{divider}RESULTS:\n{divider}"
219
+ output += " No results..\n"
220
+ output += " Solution has status: " + str(self.status.value) + "\n"
221
+ if self.error_message:
222
+ output += " Error message: " + str(self.error_message) + "\n"
223
+
224
+ # Build Provider Meta Data section
225
+ output += f"\n\n{divider}{provider.upper()} META DATA:\n{divider}"
226
+ output += (
227
+ self._pretty_print(metadata)
228
+ if metadata
229
+ else " No metadata from provider..\n"
230
+ )
231
+ return output
232
+
233
+ def subset(self):
234
+ limit = 5
235
+ subset_keys = [
236
+ "id",
237
+ "name",
238
+ "status",
239
+ "solver",
240
+ "provider",
241
+ "runtime",
242
+ "optimization_name",
243
+ "created_date",
244
+ ]
245
+ data = self.model_dump()
246
+ data["optimization_name"] = data["optimization"]["name"]
247
+ output = ""
248
+ data_subset = {key: data.get(key) for key in subset_keys if key in data}
249
+ output += self._pretty_print(data_subset)
250
+
251
+ # Build Results section
252
+ results = data.pop("results")
253
+ if results:
254
+ output += "results:\n"
255
+ output += (
256
+ f"{len(results)} results found. Displaying first {limit} results.\n"
257
+ )
258
+ for i, result in enumerate(results, start=1):
259
+ if i > limit:
260
+ output += "....\n"
261
+ break
262
+ r = f"Result {i}:\n"
263
+ r += (
264
+ f" {str(result)[:150]} ....\n"
265
+ if len(str(result)) > 150
266
+ else f" {result}\n"
267
+ )
268
+ output += r
269
+ else:
270
+ output += "results:\n"
271
+ output += " No results..\n"
272
+ output += " Solution has status: " + str(self.status.value) + "\n"
273
+ if self.error_message:
274
+ output += " Error message: " + str(self.error_message) + "\n"
275
+ return output
276
+
219
277
 
220
278
  class UseCaseResult(BaseModel):
221
279
  representation: Any
@@ -376,6 +376,8 @@ class Loop(BaseParameter):
376
376
  Energy level that the algorithm tries to reach.
377
377
  rtol: float
378
378
  Relative tolerance for convergence.
379
+ rtol: float
380
+ Relative tolerance for convergence.
379
381
  atol: float
380
382
  Absolute tolerance for convergence.
381
383
  """
@@ -383,7 +385,8 @@ class Loop(BaseParameter):
383
385
  max_iter: Optional[int] = 100
384
386
  max_time: int = 5
385
387
  convergence: int = 3
386
- target: Optional[float] = DEFAULT_RTOL
388
+ target: Optional[float] = None
389
+ rtol: float = DEFAULT_RTOL
387
390
  atol: float = DEFAULT_ATOL
388
391
 
389
392
 
@@ -1,5 +1,13 @@
1
1
  from luna_sdk.schemas.solver_parameters.base_parameter import BaseParameter
2
2
  from luna_sdk.schemas.solver_parameters.dwave import Embedding, SamplingParams
3
+ from pydantic import StringConstraints
4
+
5
+ import sys
6
+
7
+ if sys.version_info >= (3, 9):
8
+ from typing import Annotated
9
+ else:
10
+ from typing_extensions import Annotated
3
11
 
4
12
 
5
13
  class QuantumAnnealingParameters(BaseParameter):
@@ -13,7 +21,12 @@ class QuantumAnnealingParameters(BaseParameter):
13
21
  sampling_params: SamplingParams
14
22
  Parameters for the sampling. See https://docs.dwavesys.com/docs/latest/c_solver_parameters.html
15
23
  for more details.
24
+ qpu_backend: str
25
+ Specific D-Wave quantum processing unit (QPU) for your optimization
16
26
  """
17
27
 
18
28
  embedding: Embedding = Embedding()
19
29
  sampling_params: SamplingParams = SamplingParams()
30
+ qpu_backend: Annotated[
31
+ str, StringConstraints(strip_whitespace=True, min_length=1)
32
+ ] = "default"
@@ -1,9 +1,16 @@
1
1
  from typing import Any, Dict, List, Optional
2
2
 
3
- from pydantic import BaseModel, Field
3
+ from pydantic import Field, StringConstraints
4
4
 
5
5
  from luna_sdk.schemas.solver_parameters.base_parameter import BaseParameter
6
6
 
7
+ import sys
8
+
9
+ if sys.version_info >= (3, 9):
10
+ from typing import Annotated
11
+ else:
12
+ from typing_extensions import Annotated
13
+
7
14
 
8
15
  class RRQuantumAnnealingSamplingParams(BaseParameter):
9
16
  """
@@ -69,6 +76,8 @@ class RepeatedReverseQuantumAnnealingParameters(BaseParameter):
69
76
  The target energy for the solving process.
70
77
  check_trivial: bool
71
78
  Whether to check for trivial variables. Checking for trivial variables means an overhead. On the other hand, when set to `False`, trivial variables, i.e., variables without interactions, will lead to a runtime error.
79
+ qpu_backend: str
80
+ Specific D-Wave quantum processing unit (QPU) for your optimization
72
81
  """
73
82
 
74
83
  sampling_params: RRQuantumAnnealingSamplingParams = (
@@ -82,3 +91,6 @@ class RepeatedReverseQuantumAnnealingParameters(BaseParameter):
82
91
  max_iter: int = 10
83
92
  target: Optional[Any] = None
84
93
  check_trivial: bool = True
94
+ qpu_backend: Annotated[
95
+ str, StringConstraints(strip_whitespace=True, min_length=1)
96
+ ] = "default"
@@ -1,11 +1,9 @@
1
1
  from typing import Any, Optional
2
2
 
3
- from pydantic import BaseModel
3
+ from .base import Tabu
4
4
 
5
- from luna_sdk.schemas.solver_parameters.base_parameter import BaseParameter
6
5
 
7
-
8
- class TabuSearchParameters(BaseParameter):
6
+ class TabuSearchParameters(Tabu):
9
7
  """
10
8
  Tabu Search is a heuristic optimization method that works with the help of a tabu list.
11
9
  Initially, random states are chosen in the solution landscape.