Repository: quantumlib/Cirq

Issue:
Moment should have `operation_at`
There is a method called this on `Circuit`. It would make sense to live on `Moment` and then the circuit method could dispatch to it


Discussion:
This sounds like a reasonable and simple improvement, though moment can be indexed with the qubit (`moment[q]` returns the operation on that qubit), isn't it superfluous to introduce `operation_at`? 
Oh I didn't realize you could index into it like that. In any event, `Circuit.operation_at` should use that functionality
That is true, we could use moment[q] in Circuit.operation_at - just to clarify do you think it would be valuable to add `operation_at` to Moment as well as it might be more discoverable than the indexing? 
I can't speak for everyone, but I would have found it if it was called `operation_at` :) 
Hi, would it be possible for me to try and add `operation_at` to Moment? I might need to read the relevant codes first as I am not entirely familiar with them.
You got it! Thanks for volunteering!
ping @exAClior - are you looking at this? Thank you!
> ping @exAClior - are you looking at this? Thank you!

Yes, I finished adding the feature, but I need to add tests for that piece of code. I will update it tonight.

Resolving patch:
diff --git a/cirq/ops/moment.py b/cirq/ops/moment.py
--- a/cirq/ops/moment.py
+++ b/cirq/ops/moment.py
@@ -15,7 +15,7 @@
 """A simplified time-slice of operations within a sequenced circuit."""
 
 from typing import (Any, Callable, Dict, FrozenSet, Iterable, Iterator,
-                    overload, Tuple, TYPE_CHECKING, TypeVar, Union)
+                    overload, Optional, Tuple, TYPE_CHECKING, TypeVar, Union)
 from cirq import protocols
 from cirq._compat import deprecated_parameter
 from cirq.ops import raw_types
@@ -97,6 +97,21 @@ def operates_on(self, qubits: Iterable['cirq.Qid']) -> bool:
         """
         return bool(set(qubits) & self.qubits)
 
+    def operation_at(self, qubit: raw_types.Qid) -> Optional['cirq.Operation']:
+        """Returns the operation on a certain qubit for the moment.
+
+        Args:
+            qubit: The qubit on which the returned Operation operates
+                on.
+
+        Returns:
+            The operation that operates on the qubit for that moment.
+        """
+        if self.operates_on([qubit]):
+            return self.__getitem__(qubit)
+        else:
+            return None
+
     def with_operation(self, operation: 'cirq.Operation') -> 'cirq.Moment':
         """Returns an equal moment, but with the given op added.
 


Test patch:
diff --git a/cirq/ops/moment_test.py b/cirq/ops/moment_test.py
--- a/cirq/ops/moment_test.py
+++ b/cirq/ops/moment_test.py
@@ -127,6 +127,22 @@ def test_operates_on():
     assert cirq.Moment([cirq.X(a), cirq.X(b)]).operates_on([a, b, c])
 
 
+def test_operation_at():
+    a = cirq.NamedQubit('a')
+    b = cirq.NamedQubit('b')
+    c = cirq.NamedQubit('c')
+
+    # No operation on that qubit
+    assert (cirq.Moment().operation_at(a) is None)
+
+    # One Operation on the quibt
+    assert (cirq.Moment([cirq.X(a)]).operation_at(a) == cirq.X(a))
+
+    # Multiple Operations on the qubits
+    assert (cirq.Moment([cirq.CZ(a, b),
+                         cirq.X(c)]).operation_at(a) == cirq.CZ(a, b))
+
+
 def test_with_operation():
     a = cirq.NamedQubit('a')
     b = cirq.NamedQubit('b')