Unified backend submission
Describe the bug Another feature request/bug. Different backends (eg emulation vs braket.aquila) have different classes, which have different class methods. It is much more natural for them to all have the same class so any analysis can be completely back-end agnostic.
Minimal broken example
aquila_job = job.braket.aquila().run(100)
aquila_job.fetch() # Behaves as appropriate
local_job = job.braket.local_emulator().run(100)
local_job.fetch() # Should be trivial but instead raises an AttributeError
Expected behavior Every back-end should have the same methods, even if some act trivially.
run and run_async have very different behaviors. run regardless of the backend will guarantee that the results are returned to you either because its an emulation job which runs automatically or its a cloud job in which case the python code will hold until all the tasks are completed (or failed in some way). run_async will submit the tasks to the cloud but not block python.
IMO we want two methods to be able to distinguish between these two behaviors in the API.
If you could describe your particular use-case where it doesn't make sense to have this distinction between run and run_async that would be helpful for figuring out the correct API.
run_async and run have different behaviors at execution (one is blocking while one is not) but I think that the object returned from either should be the same. Of course, fetch() has interesting behavior for the run_async object and is trivial for run(). This then means that the run() method can then be:
def run(self, *args):
output = self.run_async(self,*args)
output.fetch()
return output
The use case I have in mind is building some structure where I specify the backend elsewhere and I want the rest of the code to be completely agnostic of the backend. This way, I do not have to write two codes that implement emulation vs. hardware.
That is exactly how we implement run for hardware jobs, the difference is we fetch is not blocking either, what you want is pull which is blocking.
But run_async doesn't make sense for emulation though because there is no other party running the emulation it is just your computer.
Another reason emulation isn't the same as hardware is that the emulator always completes the task, while a cloud task has many different statuses. sometimes a cloud task can fail which requires a completely different API for cloud batches because you need to do things like filtering out failed or un-submitted tasks, fetching the status of tasks, fetching results of tasks, polling results of tasks, etc. the behavior is much more rich and it just doesn't make sense to have that for the local emulator jobs.
I really hope you look at the tutorials, these show how you can combine emulation and hardware submission making use of the different API's