Closed jvanstraten closed 3 years ago
The result must be the same as before the refactoring/pass management rewrite, for as far as passes/options were not removed.
This is tested by every test in the test suite from before pass management was updated.
Basically, the old-fashioned way within python, but with compiler configuration specified in the platform, with compatibility mode enabled.
TODO: test case(s).
That is, use the new system for new features, but with as much backward compatibility as possible.
Clean build. Clean docbuild. Now reading documentation.
Python API: get_passtypes retrieves documentation but name looks like something retrieving a handle on e.g. the passes: "get...". Prefer that documentation retrieval gets other name prefixes such as "print", as used by later APIs.
Python API: get_passtypes retrieves documentation but name looks like something retrieving a handle on e.g. the passes: "get...". Prefer that documentation retrieval gets other name prefixes such as "print", as used by later APIs.
@jvansomeren
While print_*
versions of all documentation retrieval functions exist, just dumping to stdout is not always what you want. I would argue that the primitive function is always a getter that returns a string (which you can then print, or in the case of docs/conf.py convert to reStructuredText fragments), but for compatibility and consistency a print_*
version should exist for all documentation getters as well.
That said, the name of that particular doc getter could indeed be changed to better express what it does, for example [get|print]_pass_type_docs()
, otherwise it might be confused with something that just returns a list of available pass type names (for which there is no API right now, though one could easily be added). Alternatively I could replace the get_
prefix with for example dump_
for all documentation getters. Thoughts?
ETA: to be clear, the difference between the get_
and print_
functions is that the former returns the result as a string, while the latter prints it to stdout and returns None
/void
. Otherwise they are identical (both API calls chain to dump_*
in the C++ world, which takes a std::ostream
and line prefix string as arguments).
@wvlothuizen
Wheels built by CI according to e426c1e (Python 3.9) and 933163e (Python 3.6 through 3.8) should now be available for further testing via pip3 install qutechopenql==0.8.1.dev6
for Windows, MacOS, and Linux (but of course the new APIs are still unstable as per code review).
I would then propose to prefix the string returning getters with dump instead of get.
In Python API, compilation strategy is mentioned, a default compilation strategy which not be good enough and that you can change it. Only in class Platform it is described (with the compiler config) while it should be described in class Compiler at least.
What is the use of pass groups? One can make them, set options to subpasses. There are so many interfaces but it is not clear when reading them why they are there. The compiler config file allows to specify a hierarchy. Wildcards are allowed in set_option but only (?) to select subpasses, seemingly not as prefix of the path. Set_option_recursively sets an option to all passes (that support the option). I propose to undocument pass groups or to take them out of the implementation until we have a clear use case for them.
Some use cases I envisioned for pass groups, off the top of my head:
construct()
; the on_construct()
virtual function allows for this behavior), at which point the group APIs would be useful if you're a power user and want to change things anyway, or want to insert an analysis pass halfway or something.Before we decided to remove the many CC-light-specific passes, I was intending to group the passes that were previously hardcoded as a group in backend in the default configuration. I intended to do the same with the mapper (make subpasses for initial placement, heuristic routing, and the post-route decomposition thing), but tearing those components apart was more difficult than I thought, so I ended up giving up on it. So, right now, indeed, I don't see a practical use case.
Even still, I don't understand why you'd then remove a feature that's already been built and documented. Sure, if something breaks or is otherwise in the way and no one is using it, get rid of it, I guess. But this hasn't even seen the light of day yet.
In general I find the "I don't see a use case" argument moot, because someone else might. You even found yourself at the other end of the argument with QI and the mapper. Why not present the user with an option to enable it (if indeed it is simple to implement)? Because the others "didn't see a use case." It feels so counterproductive. Isn't the end goal to make a tool, something that's useful in general? Not for ourselves, but for our users, so if there's any scenario where something might be helpful to someone now or in the future, why not leave it in? An elegant interface is one where everything has been reduced to the basic building blocks (perhaps with shorthand notation for commonly-used things), but with as many of those building blocks as possible.
If you feel strongly about this though, well, deleting stuff is easy...
Wildcards are allowed in set_option but only (?) to select subpasses, seemingly not as prefix of the path
I'm not sure what you mean by this exactly. But the notation aims to follow the same semantics of file globs (when thinking of passes as directories). A *
selects all subdirectories (subpasses) within a directory (group), and (with some implementation constraints) **
matches one or more hierarchy levels at once. Some random examples:
root y.b.v.option y.*.option y.**.option **.option
|- x - - - X
|- y (group)
| |- a - X X X
| |- b (group)
| | |- u - - X X
| | |- v X - X X
| | '- w - - X X
| '- c - X X X
'- z - - - X
The only differences with glob are that directories (passes) either have subdirectories (subpasses) or files (settable options), and globbing the names of the files (options) makes no sense, so those cases aren't handled. Also, y.**.v.option
would logically select only y.b.v
, but currently throws an exception, because **
is only supported as the last non-option element, because something made that annoying to implement, so for the sake of efficiency I didn't yet.
set_option_recursively
just does set_option
with a **.
prefix. It's meant to be a less-cryptic alternative for something you might do relatively often, like c.set_option_recursively('output_prefix', 'some/output/folder/%N')
to change the output directory for all passes at once.
One thing I do feel is missing here still is a way to select options based on pass type, so for example to set an option only for all clifford optimizers in the pass list, even if a similarly named option might exist for other pass types at some point as well. This also just didn't make the cut because I was trying to restrict myself to easy-to-implement stuff.
Note finally that the user isn't supposed to read the API reference first or even at all, there's supposed to be a user manual in front of it that guides them through basic usage. I'll concede that the API class documentation is very sparse right now and could be expanded, and that there are a lot of functions in the API reference that may not be useful right now, but just keep in mind that an API reference doesn't aim to teach someone how to use the corresponding library, in the same way that a dictionary doesn't aim to teach someone how to speak the corresponding language.
I am confused about documentation.
What is a user, what is a developer?
What is a user? OpenQL is a compiler. So a user just uses it to compile a quantum program. But in doing so can set/unset options, add/delete passes, anything that the API allows. But also, the user must be able to understand what these mean, what a pass does and what the effect is when he adds/deletes passes. Of that the fundament is the IR. Therefore, the user documentation must also explain the structure and meaning of this IR, not only as external human readable thing but also as internal thing, because the external readable IR adds syntax and such which obscure the internal IR. This internal IR need not be described in terms of its actual implementation because that adds C++ details which again may obscure the meaning and clarity of the internal IR: it is about meaning, not syntax.
Anything not in the API is the domain of the developer: writing a new pass, extending/updating the IR, changing/writing a configuration file, etc.
Now, a user as described above may be able to do more than a 'simple user' may want to know. So one may consider a 'simple user' to be one who does not add/delete passes, who relies on internal defaults of pass order, who uses OpenQL out of the box, and therefore does not need to understand the internal IR to the depth as required for the 'advanced user'. For the 'simple user' it suffices to describe the IR in terms of what gets into OpenQL and what comes out. So here the cQASM documentation may be a start, supplemented by the variations that it supports (with/without mapping, with/without timing, etc.).
I propose to explain more clearly the target audience and the relation of the chapters of documentation to those kinds of audience in 'Overview', at the start of documentation.
get_custom_instructions => dump_custom_instructions gate(... condstring:str) -> none: without condregs? This API can be taken out. measure(...b0:Int)->none: specifies b0 to be float in the description
When I say "user," I'm talking about what you describe as a "simple user." Everyone in DiCarloLab except Wouter falls into that category, so I'd say it's the majority of our users (although I don't actually know how many people work in DiCarloLab). The Quantum Inspire people as well as entirely new users, no matter their intention, would also fall into this category. IMO they need the following things, and only the following things, in "OpenQL basics":
This part is meant to be "read like a book;" it should be a tutorial that the user can follow to get a basic idea of what OpenQL is, how to get it installed, and how to get a baseline Python file up and running that works on their machine. But that also means it needs to be short and interesting for everyone; if you start with "you first have to know X and Y and Z," especially when that isn't necessarily true for what a particular kind of user wants out of OpenQL, no one will actually read it. The "more information" part, on the other hand, should not read like a book, but act as additional information for parts referred to in basics, should a particular user decide for themselves that they want to know more about a particular subject. No one is supposed to read everything in a reference.
In my mind, there should be roughly three sections (with target audiences):
The latter is mostly meta stuff for the project right now, but I was intending to stick the really in-depth things from what's currently in OpenQL basics about how the implementation works either in there or in comments inside the code. The not as in-depth things should go in the pass documentation (so its source is inside the code, it can be queried from within an interactive Python console, and pops up in the "Supported passes" section of the reference). In the basics section the mapper, scheduler, optimizers, etc should be introduced, but with no more detail than what you put in your OpenQL introduction slides.
The target audience etc. should definitely be described in the overview/introduction! No argument from me there. But I'd always only write that after having written everything else already.
Finally, you mention pointing basic users to the cQASM documentation, which has me very confused. That is very much reference information, and information that only works with context at that, since every "user" of cQASM (as in piece of software that includes libqasm) has its own way of interpreting the semantic tree generated by it. It's absolutely not libqasm's place to document that OpenQL discards timing information when you do basically anything except code generation, for instance (libqasm happens to be used by OpenQL, but it's certainly not a part of it). You'd first have to know that we're using it as an impromptu compiler IR and what that means before you can even begin to understand anything in that documentation and actually arrive at correct conclusions. The same thing applies for Quantum Inspire; I see the libqasm documentation more as documentation for the QI people who have to update their frontend and then have to update their documentation, than as something for the end user. Just like how C++ users don't tend to read the C++ language specificationl heck, it's not even publicly available.
So, the basics section should introduce cQASM as OpenQL uses it at some point in a clear and concise way, very clearly stating which subset OpenQL supports at the input and which subset it generates at the output, with a link to libqasm's documentation for further details at the end. There should also be a note there that the cQASM generated by OpenQL is not always actually valid cQASM, because it can't be right now (since cQASM 1.x does not support control-flow, and I'm 100% sure that the generator doesn't generate valid 1.1 syntax for classical constructs either yet, though it could probably be modified to do so), there is the whole skip/wait debacle that still needs to be dealt with, it's going to use custom gate names rather than only cQASM's default gateset, the operand lists may be different (measure insns getting their bit result register made explicit, crk being converted to cr, the angle op of cr not even being printed because it's not in the list of insns with an angle) etc., and we don't just want to throw an error when unrepresentable IR constructs are used, because it also serves as debug output.
I'm going to be AFK (driving) for the rest of the day, so I'll respond again for new stuff that pops up tomorrow.
In this light we might add to the API functions an annotation "for advanced users only", after having defined/introduced "advanced user" in the introduction, or, more preferably, to the classes of those APIs. Because "user" == "people using API" is not true anymore otherwise. Note that Miguel et al explicitly asked for modularity because they wanted control over which passes would be included in the compiler; when they want (and must be) able to take such decisions independent of us, they must know of IR attributes such as "with mapping" and "with timing". Yes, and with cQASM I meant just enough to see the match between quantum gates in literature and those of OpenQL, not syntax, comment conventions, etc.
I wrote:
I propose to undocument pass groups or to take them out of the implementation until we have a clear use case for them
I don't mean to discard and forget them. From my CoSy background I see several missed opportunities (or didn't see them yet) and don't want to get into a backward compatibility issue when we would want to copy some of CoSy's engine design into OpenQL's pass group and option design. The pass groups are about 80% CoSy's engine classes and some simple additions could turn that into 120%; that +20% because we encountered deficiencies in CoSy as well in the end such as lack of dynamics wrt pass management that are already in OpenQL. So the easiest would be to keep them out of the documented interfaces. And then I would like to:
This requires a face2face meeting, to save time.
Regarding Topology::sort_neighbors_by_angle
, it belongs to Topology in my opinion. But it is a thing that is not mature yet. It has to do with subsetting the qubits. So could be used to define cores or particular sections of qubits with particular functionalities. In this case, the section contains those that are on the shortest path between two given qubits. But a section may have attributes like being convex (any shortest path between two qubits in the section only contains qubits in the section), being connected.
In the current case, the space of connections is planar, i.e. connections only cross in qubits (nodes).
With non-planar grids, the spaces become higher-dimensional.
Fully connected grids have the highest dimension.
Reading this, I fear that some of the ibm grids are non-planar and that thus this sorting doesn't work for those grids, i.e. we have a bug.
The cc_light default config file has a wrong cnot decomposition:
"gate_decomposition": {
"cnot %0,%1" : ["ry90 %0","cz %0,%1","ry90 %1"]
}
It should be (note the ry90 %0
to ym90 %1
gate change):
"gate_decomposition": {
"cnot %0,%1" : ["ym90 %1","cz %0,%1","ry90 %1"]
}
Option generate_code is still used by the multi-core branch. When no, the final code generation is not done. Option mappathselect with value borders doesn't follow the borders of the chip but of the search space provided that the chip's coupling graph is planar. Option maptiebreak 's first/last values assume that the coupling graph is planar and neighbors were sorted; and assume knowledge on how the alternatives are generated then (first is left-most alternative with 2q near target, last is right-most alternative with 2q near source). Option use_default_gates: TODO must be moved to TODO section of documentation. Option write_qasm_files: end of sentence is incorrect.
With the visualizer, radius etc is in pixels. Isn't a pixel a variable thing, i.e. can it be that the configuration needs to be updated for different pixel density?
With the pass cQASM reader, the uninitiated reader doesn't understand the relation between lib qasm and cQASM reader.
Several options have a file name string as value: cqasm_file
, gateset_file
, output_prefix
, and probably several more. It is not clear how these file name strings are interpreted: are these absolute path names, are these relative to the installation root, are these relative to the current directory? Is there something to control this?
Mapper pass: I would like to discuss what it does and how it can be improved. The lookahead_mode
is troubled by the interaction with recursion and that only subsets of gates (2q gates, nonNN 2q gates) are relevant in lookahead; of course 1q gates and NN 2q gates can be immediately mapped. Perhaps the recursion should be taken out of the documentation and the lookahead_mode
be reduced to a mode without recursion.
Without recursion, the lookahead_mode
option implies:
no
: just map the gates in the order of the circuit; other modes assume a dependence graph and avlist; a 1q gate or a NN 2q gate maps trivially; map a nonNN 2q gate by generating alternatives for this nonNN 2q gate and selecting the best
1qfirst
: map the 1q gates before any 2q gates in avlist until only 2q gates remain; then map one, i.e. the most critical 2q gate by generating alternatives for this nonNN 2q gate and selecting the best
noroutingfirst
: map the 1q gates and NN 2q gates in avlist until only nonNN 2q gates remain; then map one, i.e. the most critical nonNN 2q gate by generating alternatives for this nonNN 2q gate and selecting the best
all
: map the 1q gates and NN 2q gates in avlist until only nonNN 2q gates remain; then generate alternatives for all nonNN 2q gates and map that nonNN 2q gate corresponding to the best alternative selected.
path_selection_mode
: not chip border but search space border, and only if coupling graph is planar
recurse_on_nn_two_qubit
: this is the option interfering during recursion with lookahead_mode; this one and the following recursion options could be suppressed from documentation.
reverse_swap_if_better
: its implementation may even be exactly wrong; and it depends on swap decomposition on the particular target, so perhaps it should be made more clear in which cases it does something and what it does then, also to make it independent of the target
tie_break_method
: first and last depend on knowledge of alternative path generation; and taking the first/last is then only deterministic when the coupling graph is planar
Resources and the new way of specifying resource constraints, reading the documentation.
This made the resource specification more powerful: more types of resources can be described.
Regarding Instrument resource, does the detuned_qubits resource match the description of general operation in the Instrument resource section? A mw and a flux don't need to have the same duration for running in parallel, nor need to start in the same cycle. The instrument in this case is the particular frequency choice for a qubit: default or detuned. Mw needs default; some flux need detuned on a qubit defined by the flux operand pair. Qubit exclusive use is assumed (other instrument).
The section reads as an introduction to resources and is very useful in this respect, so should be kept but must be made accurate. I propose to add that this is a rationale/example/motivation, not a specification; or to add other types of resources (such as detuned_qubits) that are somehow different must must be supported as well. Or that the if and only if
before the first bullet list is updated.
Key here is they use the same instrument function;
, not the other ones.
For a 1q mw and a 2q flux to be in parallel regarding the detuned_qubits resource, they must not both use the same instrument object. In the detuned_qubits example config, the 6 objects model the 6 qubits where a conflict could arise. The 1q and 2q select the instrument object thru different size-specialized predicates.
So same instrument function
means: same instrument (object) in the set of a particular instrument type
.
Regarding the configuration structure: a required condition for an incoming gate to match a predicate is:
its instruction set definition object has values for all keys specified; When one forgets to add a particular key in a gate specification (e.g. "mw" as "type" in "x45"), it will never be matched; could this go unnoticed somehow? If so, consider checking this somehow. I don't have an idea now.
What could be emphasized more is that there always are two gates for which one wants to know whether they can be in parallel. For each such pair one checks all resource types. When for one resource type, both gates use (select to/match) the same instruction object, they cannot be in parallel. This operational
definition is somehow assumed.
I don't understand "exclusive"
. Or, I don't understand the function section. Or, I don't understand: a list of gate keys as specified in the structure above
The original resource specs didn't support three-or-more-qubit gates because the underlying architectures don't support them. So why is their support now in?
Perhaps suppress the multi-core channel resource since it is not mature yet. There are many implicits here (deriving core index from qubit index, full core connectivity) which need ability to be specified. The documentation here is not ready yet either. The channel resource would only be allocated by inter-core-gates, a subset of 2q gates, each such gate allocates two channels, one in each core. I don't understand: This is mostly for compatibility with the original channel resource, which didn’t check for this.
With the Release procedure, I am missing the writing of Release Notes. This is a summary of what has changed, what is new, what is incompatible and gives recipes how to overcome the latter. It also summarizes what is deprecated from now on and will be removed in a later version. It need not be a lot of text but should refer to the necessary texts in the documentation; it is an entry-level document.
In C++ coding conventions, the section Namespaces appears twice. Regarding virgin constructors and an init method, I'm still curious why this was (or why I thought this was) needed in the mapper.
I concluded with reviewing the PR documentation (as generated from within the docs directory).
Up to https://github.com/QE-Lab/OpenQL/pull/405#issuecomment-831175809:
In Python API, compilation strategy is mentioned, a default compilation strategy which not be good enough and that you can change it. Only in class Platform it is described (with the compiler config) while it should be described in class Compiler at least.
Lazily added a single sentence description of what it's for (bunched in with 94a69be). This kind of thing is more something for user-manual style docs than API docs anyway.
(discussion about pass groups)
Removed all traces of pass groups that I'm aware of from the API based on QL_HIERARCHICAL_PASS_MANAGEMENT
in config.h.template
. I didn't want to remove everything completely, because I had to change a lot of docstrings to make everything sane again.
get_custom_instructions => dump_custom_instructions
This is an old API, not one that I added, so for backward compat it should stay in. I've added a dump synonym for it and deprecated the get version though.
gate(... condstring:str) -> none: without condregs? This API can be taken out.
It's for the always/never variants, and mirrors the internal function signature. Leaving it in allows gates to be added procedurally using gate(... condstring, *condregs)
regardless of condition type (or lack thereof). Also, it's rather annoying to take it out because it's generated from C++'s optional argument system.
Also fixed a few compilation instruction things found by Quinten.
Up to https://github.com/QE-Lab/OpenQL/pull/405#issuecomment-832481890:
(sort_neighbors_by_angle stuff)
Replaced the FIXME with a TODO note referring to this comment, don't know what else to do with it for now.
(CC-light CNOT gate decomposition)
Fixed, but note this changed golden files. It wasn't broken during refactoring.
Option generate_code is still used by the multi-core branch. When no, the final code generation is not done.
It's defunct because the QISA code generation pass was removed, so regardless of whether it's yes or no, final code generation is not done.
Option mappathselect with value borders doesn't follow the borders of the chip but of the search space provided that the chip's coupling graph is planar.
Updated.
Option maptiebreak 's first/last values assume that the coupling graph is planar and neighbors were sorted; and assume knowledge on how the alternatives are generated then (first is left-most alternative with 2q near target, last is right-most alternative with 2q near source).
Updated.
Option use_default_gates: TODO must be moved to TODO section of documentation.
I'm not sure what you mean by this, and in general the option documentation is generated, so it's not really possible to add RST directives and whatnot to them without making everything vastly more complicated.
Option write_qasm_files: end of sentence is incorrect.
Fixed.
With the visualizer, radius etc is in pixels. Isn't a pixel a variable thing, i.e. can it be that the configuration needs to be updated for different pixel density?
I highly doubt that the CImg library is aware of pixel density and GUI scale, and if not, it's not really something that can easily be fixed. Internally CImg just makes a bitmap image (which it can also write to a file as such) which logically uses pixel units, and eventually makes a window that displays this bitmap. It's no more intelligent than that. If this is/becomes a problem maybe something can be tacked on to fix it later, but that'd be a feature request that really shouldn't be bunched up in a refactoring commit.
With the pass cQASM reader, the uninitiated reader doesn't understand the relation between lib qasm and cQASM reader.
Added short explanation of relationship between the two, with reference to libqasm's ReadTheDocs page.
(filename relativeness)
Anywhere this is not specified, filenames must either be absolute or relative to the current working directory as tracked by the OS. IMO this is just how computers work, so I really don't feel like this is something worth repeating everywhere...
We could quite easily change the behavior since all file I/O is wrapped by utils
, but I don't really see why in this case? I suppose I could see it be useful when these option values are specified in a compiler configuration file, but any implementation for that would have to be really contrived, because it would mean there are special cases for certain options when they're specified in a certain way...
For https://github.com/QE-Lab/OpenQL/pull/405#issuecomment-832506285:
Mapper pass: I would like to discuss what it does and how it can be improved. [...]
Changing the functional implementation of the mapper should be a separate issue/PR, especially at this point in the process.
Without recursion, the
lookahead_mode
option implies: [...]
Updated option docs accordingly.
path_selection_mode
: not chip border but search space border, and only if coupling graph is planar
Already updated along with the global option.
recurse_on_nn_two_qubit
: this is the option interfering during recursion withlookahead_mode
; this one and the following recursion options could be suppressed from documentation.
As I mentioned in an earlier comment, the option documentation (including pass option documentation) is generated from the options exactly as they exist in the sources and thus include everything, and I firmly believe this is a good thing. That's what it's a reference for. So, instead of surpressing, I added notes stating that these are advanced and unstable options, for recurse_on_nn_two_qubit
including that it affects lookahead_mode
in a currently-undocumented way.
reverse_swap_if_better
: its implementation may even be exactly wrong; and it depends on swap decomposition on the particular target, so perhaps it should be made more clear in which cases it does something and what it does then, also to make it independent of the target
I feel like the docstring I added to it already explained this, but I expanded upon it to make it more clear. IMO it's up to the user to define the composition such that it complies with the convention.
I also more properly documented the general behavior of the mapper, and noted there what the requirements on the gate/decomposition rule definitions in the platform are.
For https://github.com/QE-Lab/OpenQL/pull/405#issuecomment-832571528:
Regarding Instrument resource, does the detuned_qubits resource match the description of general operation in the Instrument resource section? [...]
You're right, good catch... Also, reading your comment and rereading the docs for this section, it seems a bit weird that the instruments are not by qubit (i.e. whether an instrument is detuning the qubit or not) but by edge. I think the latter is sound though (and was probably easier to generate from the old structure)...
I remember that when I worked on generalizing the instruments before (in a more advanced way rather than just ad-hoc what seemed to be needed to model the CC-light resources more generally) I modelled instrument usage as a particular function per cycle, rather than using cycle ranges. The alignment requirement could then be modelled by using a different function for the first, last, and any further cycles for all gates, while the behavior otherwise would be that alignment is not required at all. This is probably why I didn't realize that this (simpler) implementation doesn't work that way.
Unfortunately that means that the reservations tracker thing I made is also not as general as I would have liked it to be, so I should probably redo that (this doesn't necessarily take a lot of time, maybe a day or two). So I'll work through the other issues first.
Regarding the configuration structure: a required condition for an incoming gate to match a predicate is: [...]
Yes, it could go unnnoticed, because by definition none of these keys are required. But I can list a plethora of other issues similar to or IMO more important than this one with the current platform configuration system; any typo anywhere can easily make a key not recognized, have its default be used instead, and not be caught because historically people have been dumping no-longer-used keys all over the place, so I can't just throw an error for unrecognized things.
However, users should ideally not be forced to specify repetitive things like this manually to begin with. That's what the platform preprocessing thing for architectures is for. If a particular platform requires that each gate has a "type" key and has requirements on what values it may map to, this should be checked there, not by the (generalized) instrument resource. Similarly, this logic may desugar more easily specifiable resources into instrument resource configurations.
What could be emphasized more is that there always are two gates for which one wants to know whether they can be in parallel. For each such pair one checks all resource types. When for one resource type, both gates use (select to/match) the same instruction object, they cannot be in parallel. This
operational
definition is somehow assumed.
I don't understand what you mean by this. Please rephrase.
I don't understand "exclusive". Or, I don't understand the function section. Or, I don't understand: a list of gate keys as specified in the structure above
Admittedly the section on how to specify the value for "function"
is a bit confusingly written, although I'd argue that
The instrument function is configurable for each particular gate based on one or more custom keys in the instruction set definition of the platform configuration file. It's also possible to specify that there is only a single function (effectively, this removes the first condition in the list above), or to specify that all functions are mutually exclusive (in which case gates using the same instruments can never be parallelized).
in the behavioral description is good enough? Either way, I'll have to rewrite the docs when I update the resource to more properly support qubit detuning.
The original resource specs didn't support three-or-more-qubit gates because the underlying architectures don't support them. So why is their support now in?
I added it so specifying detuning via "3-qubit" CZ gates (i.e. with the detuned qubit(s) made explicit) could also be supported, and because it seemed like a reasonable generalization in general.
Perhaps suppress the multi-core channel resource since it is not mature yet. There are many implicits here (deriving core index from qubit index, full core connectivity) which need ability to be specified.
How qubits map to cores is a topology thing, and is documented (sparsely, I'll admit, but it's there) in the topology configuration description. Though the core_index = floor(qubit_index / num_cores)
thing was missing from there.
The documentation here is not ready yet either. The channel resource would only be allocated by inter-core-gates, a subset of 2q gates, each such gate allocates two channels, one in each core. I don't understand:
This is mostly for compatibility with the original channel resource, which didn’t check for this.
I don't understand what you mean. The documentation describes the resource as I (re)implemented, which is a basic generalization of what was there:
"inter_core_required"
is set, any gate (matching the predicates, if any) operating on qubits from different cores will allocate a channel for each core involved. This is, IMO, what the resource should be doing, but not what the implementation was doing;"inter_core_required"
is explicitly disabled, any gate matching the predicates will allocate a channel for all cores involved, regardless of whether it actually uses qubits from different cores. For whatever reason, you were doing this using a special gate type (modelled as a predicate) as generated by the mapper via tswap/tmove, rather than just checking whether a two-qubit gate operates on qubits belonging to different cores.The "communication_qubit_only"
augments the above when set, by ignoring qubit operands that are not communication qubits.
TODO:
With the Release procedure, I am missing the writing of Release Notes.
It was very vaguely in there (though I called it a short changelog), but I expanded on it now and added a few other missing steps while I was at it. I was intending to update it while doing the actual release, so I hadn't looked at it much yet.
In C++ coding conventions, the section Namespaces appears twice.
Fixed.
Regarding virgin constructors and an init method, I'm still curious why this was (or why I thought this was) needed in the mapper.
Just because C++ is annoying with its member initialization syntax. There are ways around it, but it quickly becomes a lot more messy than it's worth. It's easier to just wrap a class member in utils::Opt
or utils::Ptr
when you can't easily initialize it before the constructor's function body; this lets you do everything that virgin constructor + init lets you do, but ensures that you can never use the object accidentally before initializing it (you'll get a runtime error if you do, stating that you're dereferencing an empty Opt
or Ptr
) and still lets you use RAII for the affected class where this issue doesn't exist.
I believe that's everything except for the functional limitations for the instruments and the still-missing user docs and tests for the new compiler API.
Followup on #364
In this PR
[x] Removal of unused code as agreed upon
[x] General cleanup on a per-file basis
new
allocations to smart pointers to vastly reduce memory usage and prevent segfaultsbuffer_insertion.[cc|h]
circuit.[cc|h]
classical.[cc|h]
clifford.[cc|h]
commute_variation.[cc|h]
compiler.[cc|h]
decompose_toffoli.[cc|h]
eqasm_compiler.[cc|h]
gate.[cc|h]
hardware_configuration.[cc|h]
interactionMatrix.[cc|h]
ir.[cc|h]
kernel.[cc|h]
latency_compensation.[cc|h]
mapper.[cc|h]
matrix.h
metrics.[cc|h]
openql.h
openql_i.[cc|h]
optimizer.[cc|h]
options.[cc|h]
platform.[cc|h]
program.[cc|h]
ql_config.h
qsoverlay.[cc|h]
report.[cc|h]
resource_manager.[cc|h]
scheduler.[cc|h]
unitary.[cc|h]
visualizer.h
visualizer_cimg.[cc|h]
visualizer_circuit.[cc|h]
visualizer_common.[cc|h]
visualizer_interaction.[cc|h]
visualizer_mapping.[cc|h]
visualizer_types.h
write_sweep_points.[cc|h]
arch/cc_light/cc_light_eqasm.[cc|h]
arch/cc_light/cc_light_eqasm_compiler.[cc|h]
arch/cc_light/cc_light_resource_manager.[cc|h]
arch/cc/backend_cc.[cc|h]
arch/cc/bundle_info.h
arch/cc/codegen_cc.[cc|h]
arch/cc/datapath_cc.[cc|h]
arch/cc/options_cc.h
arch/cc/settings_cc.[cc|h]
arch/cc/types_cc.h
arch/cc/vcd_cc.[cc|h]
cqasm/cqasm_reader.[cc|h]
passes/passes.[cc|h]
passes/passmanager.[cc|h]
[x] Basic IR restructuring
tree-gen
base and reference classes for IR, to smoothen transition to generated tree (if generating it isn't more trouble than it's worth)GateKernelGateClassical[x] Basic platform restructuring
"eqasm_compiler"
key for specifying compiler configuration, either via filename or in-placetests
directory for themarch.*
)src/arch/*
, baked into the OpenQL library via resource generation/cc
cc_light
none
[x] Revise/future-proof pass management
eqasm_compiler
class (no difference now between it and regular passes)[x] Revise/future-proof resource management
ClonablePtr
abstraction to prevent the need ofclone()
code duplication in the resourcesplatform_resource_manager
class; all platforms can use all resource types, identified by name (possibly prefixed with platform type, just like pass management)[x] Revise/future-proof option system
[x] Refactor/future-proof statistics/metrics to avoid code duplication and make it easier to add more later
[x] Update Python API
ql.Platform
ql.Program
ql.Program.compile()
to new pass manager, based on the platform that the program was constructed with[x] Documentation
basically allsome of the hand-written stuff. Pretty sure everything is out of date and/or relies on internal knowledge of OpenQL's codebase.conf.py
to generate online docs based on runtime docs (available passes, available resources, and available global/pass options)[x] Figure out where the virtual-to-real qubit mapping information for the visualizer is going (SwapParameters), since the visualizer doesn't see them for some reason
Future refactoring/utility work (i.e. postponed for now)
More IR/platform restructuring
Revise gate representation and construction
Kernel
and stick it in a configurable pass insteadKernel
and stick it in a pass insteadWrap JSON loader/data structure
CRASH_AND_BURN()
.Revise logging system
Revise exception system
Add unit testing framework to build system
Distribute default configuration files with Python installation properly
tests
directory, and things stop lighting on fire outside of the context of the test suiteRevise representation of classical code/advanced IR restructuring (i.e. OpenQL implementation of cQASM 2.0)