2
2
3
3
mod decoder;
4
4
mod encoder;
5
- mod op;
6
- mod param;
5
+ pub mod extension;
7
6
7
+ pub use encoder:: { default_encoder_config, Tk1EncoderConfig , Tk1EncoderContext } ;
8
+ pub use extension:: PytketEmitter ;
9
+
10
+ use hugr:: core:: HugrNode ;
8
11
use hugr:: types:: Type ;
9
12
10
- use hugr:: Node ;
13
+ use hugr:: Wire ;
11
14
use itertools:: Itertools ;
12
- // Required for serialising ops in the tket1 hugr extension.
13
- pub ( crate ) use op:: serialised:: OpaqueTk1Op ;
14
15
15
16
#[ cfg( test) ]
16
17
mod tests;
@@ -29,8 +30,7 @@ use tket_json_rs::register::{Bit, ElementId, Qubit};
29
30
30
31
use crate :: circuit:: Circuit ;
31
32
32
- use self :: decoder:: Tk1Decoder ;
33
- use self :: encoder:: Tk1Encoder ;
33
+ use self :: decoder:: Tk1DecoderContext ;
34
34
35
35
pub use crate :: passes:: pytket:: lower_to_pytket;
36
36
@@ -66,11 +66,11 @@ pub trait TKETDecode: Sized {
66
66
}
67
67
68
68
impl TKETDecode for SerialCircuit {
69
- type DecodeError = TK1ConvertError ;
70
- type EncodeError = TK1ConvertError ;
69
+ type DecodeError = Tk1ConvertError ;
70
+ type EncodeError = Tk1ConvertError ;
71
71
72
72
fn decode ( self ) -> Result < Circuit , Self :: DecodeError > {
73
- let mut decoder = Tk1Decoder :: try_new ( & self ) ?;
73
+ let mut decoder = Tk1DecoderContext :: try_new ( & self ) ?;
74
74
75
75
if !self . phase . is_empty ( ) {
76
76
// TODO - add a phase gate
@@ -85,31 +85,29 @@ impl TKETDecode for SerialCircuit {
85
85
}
86
86
87
87
fn encode ( circ : & Circuit ) -> Result < Self , Self :: EncodeError > {
88
- let mut encoder = Tk1Encoder :: new ( circ) ?;
89
- for com in circ. commands ( ) {
90
- let optype = com. optype ( ) ;
91
- encoder. add_command ( com. clone ( ) , optype) ?;
92
- }
93
- Ok ( encoder. finish ( circ) )
88
+ let config = default_encoder_config ( ) ;
89
+ let mut encoder = Tk1EncoderContext :: new ( circ, config) ?;
90
+ encoder. run_encoder ( circ) ?;
91
+ encoder. finish ( circ)
94
92
}
95
93
}
96
94
97
95
/// Load a TKET1 circuit from a JSON file.
98
- pub fn load_tk1_json_file ( path : impl AsRef < Path > ) -> Result < Circuit , TK1ConvertError > {
96
+ pub fn load_tk1_json_file ( path : impl AsRef < Path > ) -> Result < Circuit , Tk1ConvertError > {
99
97
let file = fs:: File :: open ( path) ?;
100
98
let reader = io:: BufReader :: new ( file) ;
101
99
load_tk1_json_reader ( reader)
102
100
}
103
101
104
102
/// Load a TKET1 circuit from a JSON reader.
105
- pub fn load_tk1_json_reader ( json : impl io:: Read ) -> Result < Circuit , TK1ConvertError > {
103
+ pub fn load_tk1_json_reader ( json : impl io:: Read ) -> Result < Circuit , Tk1ConvertError > {
106
104
let ser: SerialCircuit = serde_json:: from_reader ( json) ?;
107
105
let circ: Circuit = ser. decode ( ) ?;
108
106
Ok ( circ)
109
107
}
110
108
111
109
/// Load a TKET1 circuit from a JSON string.
112
- pub fn load_tk1_json_str ( json : & str ) -> Result < Circuit , TK1ConvertError > {
110
+ pub fn load_tk1_json_str ( json : & str ) -> Result < Circuit , Tk1ConvertError > {
113
111
let reader = json. as_bytes ( ) ;
114
112
load_tk1_json_reader ( reader)
115
113
}
@@ -122,7 +120,7 @@ pub fn load_tk1_json_str(json: &str) -> Result<Circuit, TK1ConvertError> {
122
120
///
123
121
/// Returns an error if the circuit is not flat or if it contains operations not
124
122
/// supported by pytket.
125
- pub fn save_tk1_json_file ( circ : & Circuit , path : impl AsRef < Path > ) -> Result < ( ) , TK1ConvertError > {
123
+ pub fn save_tk1_json_file ( circ : & Circuit , path : impl AsRef < Path > ) -> Result < ( ) , Tk1ConvertError > {
126
124
let file = fs:: File :: create ( path) ?;
127
125
let writer = io:: BufWriter :: new ( file) ;
128
126
save_tk1_json_writer ( circ, writer)
@@ -136,7 +134,7 @@ pub fn save_tk1_json_file(circ: &Circuit, path: impl AsRef<Path>) -> Result<(),
136
134
///
137
135
/// Returns an error if the circuit is not flat or if it contains operations not
138
136
/// supported by pytket.
139
- pub fn save_tk1_json_writer ( circ : & Circuit , w : impl io:: Write ) -> Result < ( ) , TK1ConvertError > {
137
+ pub fn save_tk1_json_writer ( circ : & Circuit , w : impl io:: Write ) -> Result < ( ) , Tk1ConvertError > {
140
138
let serial_circ = SerialCircuit :: encode ( circ) ?;
141
139
serde_json:: to_writer ( w, & serial_circ) ?;
142
140
Ok ( ( ) )
@@ -150,25 +148,30 @@ pub fn save_tk1_json_writer(circ: &Circuit, w: impl io::Write) -> Result<(), TK1
150
148
///
151
149
/// Returns an error if the circuit is not flat or if it contains operations not
152
150
/// supported by pytket.
153
- pub fn save_tk1_json_str ( circ : & Circuit ) -> Result < String , TK1ConvertError > {
151
+ pub fn save_tk1_json_str ( circ : & Circuit ) -> Result < String , Tk1ConvertError > {
154
152
let mut buf = io:: BufWriter :: new ( Vec :: new ( ) ) ;
155
153
save_tk1_json_writer ( circ, & mut buf) ?;
156
154
let bytes = buf. into_inner ( ) . unwrap ( ) ;
157
155
Ok ( String :: from_utf8 ( bytes) ?)
158
156
}
159
157
160
- /// Error type for conversion between `Op` and `OpType` .
161
- #[ derive( Display , Debug , Error , From ) ]
158
+ /// Error type for conversion between pytket operations and tket2 ops .
159
+ #[ derive( Display , derive_more :: Debug , Error , From ) ]
162
160
#[ non_exhaustive]
163
- pub enum OpConvertError {
161
+ #[ debug( bounds( N : HugrNode ) ) ]
162
+ pub enum OpConvertError < N = hugr:: Node > {
164
163
/// The serialized operation is not supported.
165
- #[ display( "Unsupported serialized pytket operation: {_0:?}" ) ]
166
- #[ error( ignore) ] // `_0` is not the error source
167
- UnsupportedSerializedOp ( SerialOpType ) ,
164
+ #[ display( "Unsupported serialized pytket operation: {op:?}" ) ]
165
+ UnsupportedSerializedOp {
166
+ /// The serialized operation.
167
+ op : SerialOpType ,
168
+ } ,
168
169
/// The serialized operation is not supported.
169
- #[ display( "Cannot serialize tket2 operation: {_0:?}" ) ]
170
- #[ error( ignore) ] // `_0` is not the error source
171
- UnsupportedOpSerialization ( OpType ) ,
170
+ #[ display( "Cannot serialize tket2 operation: {op}" ) ]
171
+ UnsupportedOpSerialization {
172
+ /// The operation.
173
+ op : OpType ,
174
+ } ,
172
175
/// The operation has non-serializable inputs.
173
176
#[ display(
174
177
"Operation {} in {node} has an unsupported input of type {typ}." ,
@@ -180,7 +183,7 @@ pub enum OpConvertError {
180
183
/// The operation name.
181
184
optype : OpType ,
182
185
/// The node.
183
- node : Node ,
186
+ node : N ,
184
187
} ,
185
188
/// The operation has non-serializable outputs.
186
189
#[ display(
@@ -193,7 +196,7 @@ pub enum OpConvertError {
193
196
/// The operation name.
194
197
optype : OpType ,
195
198
/// The node.
196
- node : Node ,
199
+ node : N ,
197
200
} ,
198
201
/// A parameter input could not be evaluated.
199
202
#[ display(
@@ -206,7 +209,7 @@ pub enum OpConvertError {
206
209
/// The operation with the missing input param.
207
210
optype : OpType ,
208
211
/// The node.
209
- node : Node ,
212
+ node : N ,
210
213
} ,
211
214
/// The operation has output-only qubits.
212
215
/// This is not currently supported by the encoder.
@@ -217,7 +220,7 @@ pub enum OpConvertError {
217
220
/// The operation name.
218
221
optype : OpType ,
219
222
/// The node.
220
- node : Node ,
223
+ node : N ,
221
224
} ,
222
225
/// The opaque tket1 operation had an invalid type parameter.
223
226
#[ display( "Opaque TKET1 operation had an invalid type parameter. {error}" ) ]
@@ -256,15 +259,42 @@ pub enum OpConvertError {
256
259
/// The given of parameters.
257
260
args : Vec < ElementId > ,
258
261
} ,
262
+ /// A node parameter output could not be evaluated.
263
+ #[ display( "Could not compute output parameter #{out_index} for operation {} given inputs [{}]." , op. name( ) , params. iter( ) . join( ", " ) ) ]
264
+ CannotComputeParams {
265
+ /// The operation being encoded
266
+ op : OpType ,
267
+ /// The input parameters.
268
+ params : Vec < String > ,
269
+ /// The output index that could not be computed.
270
+ out_index : usize ,
271
+ } ,
272
+ /// Tried to query the values associated with an unexplored wire.
273
+ ///
274
+ /// This reflects a bug in the operation encoding logic of an operation.
275
+ #[ display( "Could not find values associated with wire {wire}." ) ]
276
+ WireHasNoValues {
277
+ /// The wire that has no values.
278
+ wire : Wire < N > ,
279
+ } ,
280
+ /// Tried to add values to an already registered wire.
281
+ ///
282
+ /// This reflects a bug in the operation encoding logic of an operation.
283
+ #[ display( "Tried to register values for wire {wire}, but it already has associated values." ) ]
284
+ WireAlreadyHasValues {
285
+ /// The wire that already has values.
286
+ wire : Wire < N > ,
287
+ } ,
259
288
}
260
289
261
- /// Error type for conversion between `Op` and `OpType` .
262
- #[ derive( Debug , Display , Error , From ) ]
290
+ /// Error type for conversion between tket2 ops and pytket operations .
291
+ #[ derive( derive_more :: Debug , Display , Error , From ) ]
263
292
#[ non_exhaustive]
264
- pub enum TK1ConvertError {
293
+ #[ debug( bounds( N : HugrNode ) ) ]
294
+ pub enum Tk1ConvertError < N = hugr:: Node > {
265
295
/// Operation conversion error.
266
296
#[ from]
267
- OpConversionError ( OpConvertError ) ,
297
+ OpConversionError ( OpConvertError < N > ) ,
268
298
/// The circuit has non-serializable inputs.
269
299
#[ display( "Circuit contains non-serializable input of type {typ}." ) ]
270
300
NonSerializableInputs {
@@ -291,6 +321,19 @@ pub enum TK1ConvertError {
291
321
#[ display( "Unable to load pytket json file. {_0}" ) ]
292
322
#[ from]
293
323
FileLoadError ( io:: Error ) ,
324
+ /// Custom user-defined error raised while encoding an operation.
325
+ #[ display( "Error while encoding operation: {msg}" ) ]
326
+ CustomError {
327
+ /// The custom error message
328
+ msg : String ,
329
+ } ,
330
+ }
331
+
332
+ impl < N > Tk1ConvertError < N > {
333
+ /// Create a new error with a custom message.
334
+ pub fn custom ( msg : impl Into < String > ) -> Self {
335
+ Self :: CustomError { msg : msg. into ( ) }
336
+ }
294
337
}
295
338
296
339
/// A hashed register, used to identify registers in the [`Tk1Decoder::register_wire`] map,
0 commit comments