def __init__(self, target_gate): ''' Create a Target operation with the given target_gate as the type of the gate for the target (e.g., X for CNOT and Z for Controlled-Z). ''' Operation.__init__(self, TARGET, target_gate) self.target_gate = target_gate
def __init__(self, label, index): ''' \alpha_l ''' Operation.__init__(self, SUB_INDEXED, [label, index]) self.label = label self.index = index
def __init__(self, base, exponent): r''' Tensor exponentiation to any natural number exponent. ''' Operation.__init__(self, TENSOR_EXP, (base, exponent)) self.base = self.operands[0] self.exponent = self.operands[1]
def __init__(self, tensor, shape=None): ''' Create a Circuit either with a dense tensor (list of lists ... of lists) or with a dictionary mapping pairs of indices to Expression elements or blocks, composing an ExpressionTensor. ''' from .common import PASS if not isinstance(tensor, dict): # remove identity gates -- these are implicit tensor, _ = ExpressionTensor.TensorDictFromIterables(tensor) fixed_shape = (shape is not None) if not fixed_shape: shape = (0, 0) for idx in list(tensor.keys()): if len(idx) != 2: raise ValueError( 'Circuit operand must be a 2-D ExpressionTensor') if not fixed_shape: shape = (max(shape[0], idx[0] + 1), max(shape[1], idx[1] + 1)) if tensor[idx] == PASS: tensor.pop(idx) self.tensor = ExpressionTensor(tensor, shape) self.shape = self.tensor.shape Operation.__init__(self, CIRCUIT, [self.tensor]) if len(self.shape) != 2: raise ValueError('Circuit operand must be a 2-D ExpressionTensor') # For each row of each nested sub-tensor (including the top level), # determine which sub-tensor, if there are any, has the deepest nesting. # This will impact how we iterate over nested rows to flatten the display of a nested tensors. tensor = self.tensor self.deepestNestedTensorAlongRow = dict( ) # map nested tensor (including self) to a list that indicates the deepest nested tensor per row def determineDeepestNestedTensors(tensor): ''' Determine and set the deepest nested tensor along each row of tensor, applying this recursively for sub-tensors, and return the depth of this tensor. ''' maxDepth = 1 self.deepestNestedTensorAlongRow[ tensor] = deepestNestedTensorAlongRow = [] for row in range(tensor.shape[0]): deepestNestedTensor = None maxDepthAlongRow = 1 for col in range(tensor.shape[1]): if (row, col) in tensor: cell = tensor[row, col] if isinstance(cell, ExpressionTensor): subDepth = determineDeepestNestedTensors(cell) maxDepthAlongRow = max(maxDepthAlongRow, subDepth + 1) if deepestNestedTensor is None or subDepth > maxDepthAlongRow: deepestNestedTensor = cell maxDepth = max(maxDepth, maxDepthAlongRow + 1) deepestNestedTensorAlongRow.append(deepestNestedTensor) return maxDepth determineDeepestNestedTensors(self.tensor)
def __init__(self, expr_tensor): Operation.__init__(self, MATRIX, expr_tensor) self.tensor = self.operands if not isinstance(self.tensor, ExpressionTensor): raise ImproperMatrix( 'Matrix must be given an ExpressionTensor for its operands') if len(self.tensor.shape) != 2: raise ImproperMatrix( 'Matrix must be given a 2-dimensional ExpressionTensor') self.nrows = self.tensor.shape[0] self.ncolumns = self.tensor.shape[1]
def formatted(self, formatType, fence=False): formattedGateOperation = self.target_gate.formatted(formatType, fence=False) if formatType == LATEX: return r'\gate{' + formattedGateOperation + r'}' else: return Operation.formatted(self, formatType, fence)
def distribute(self, factorIdx): ''' Distribute over the factor at the given index. ''' from theorems import distributeTensorProdOverSum, distributeTensorProdOverSummation from proveit.number import Add, Sum factor = self.factors[factorIdx] if isinstance(factor, Add): return distributeTensorProdOverSum.specialize({ xEtc: self.factors[:factorIdx], yEtc: factor.terms, zEtc: self.factors[factorIdx + 1:] }) elif isinstance(factor, Sum): domain = factor.domain summand = factor.summand index = factor.index return distributeTensorProdOverSummation.specialize({ xEtc: self.factors[:factorIdx], Operation(f, index): summand, S: domain, y: index, zEtc: self.factors[factorIdx + 1:] }) else: raise Exception( "Don't know how to distribute tensor product over " + str(factor.__class__) + " factor")
def __init__(self, n): ''' Create some SU(n), the special unitary of degree n. ''' Operation.__init__(self, SPECIAL_UNITARY, n) self.operand = n
def formatted(self, formatType, fence=False): formattedState = self.state.formatted(formatType, fence=False) if formatType == LATEX: return r'\rstick{' + formattedState + r'} \qw' else: return Operation.formatted(self, formatType, fence)
def __init__(self, state): ''' Create a INPUT operation with the given input state. ''' Operation.__init__(self, OUTPUT, state) self.state = state
def formatter(self, formatType, fence=False): from .common import CTRL_UP, CTRL_DN, CTRL_UPDN, WIRE_UP, WIRE_DN, WIRE_LINK if formatType == LATEX: if fence: yield r'\left[' + '\n' yield r'\begin{array}{cc}' + '\n' yield r'\Qcircuit @C=1em @R=.7em {' # + '\n' for nestedRowIdx in self.generateNestedRowIndices(): #print "nestedRowIdx", nestedRowIdx if sum(nestedRowIdx) > 0: yield r' \\ ' # previous row has ended for level, circuitTensor, row, column in self.generateCircuitElementsAlongRow( nestedRowIdx): if not (row, column) in circuitTensor: yield r' & \qw' # identity gate is a quantum wire else: elem = circuitTensor[row, column] if level < len(nestedRowIdx) - 1: # we have a multigate if sum(nestedRowIdx[level:]) == 0: # we are at the top of the multigate numMultiGateRows = self.numberOfNestedRows( circuitTensor, row) yield r' & \multigate{' + str( numMultiGateRows - 1) + '}{' + elem.formatted( formatType, False) + '}' else: # below the top of the multigate, use ghost yield r' & \ghost{' + elem.formatted( formatType, False) + '}' elif elem == WIRE_LINK: yield r' & \qw' # junction, but the instruction here just needs to continue the horizontal wire elif elem == CTRL_UP: yield r' & \ctrl{' + str( Circuit._NearestTarget(circuitTensor, row, column, -1)) + '}' elif elem == CTRL_DN: yield r' & \ctrl{' + str( Circuit._NearestTarget(circuitTensor, row, column, 1)) + '}' elif elem == WIRE_UP: yield r' & \qwx[' + str( Circuit._NearestTarget(circuitTensor, row, column, -1)) + '] \qw' elif elem == WIRE_DN: yield r' & \qwx[' + str( Circuit._NearestTarget(circuitTensor, row, column, 1)) + '] \qw' elif elem == CTRL_UPDN: yield r' & \ctrl{' + str( Circuit._NearestTarget(circuitTensor, row, column, -1)) + '}' yield r' \qwx[' + str( Circuit._NearestTarget(circuitTensor, row, column, 1)) + ']' elif elem == TARGET: yield r' & ' + elem.formatted(formatType, False) else: yield r' & ' + elem.formatted(formatType, False) yield '} & ~ \n' yield r'\end{array}' if fence: yield '\n' + r'\right]' else: yield Operation.formatted(self, formatType, fence)
def _config_latex_tool(self, lt): Operation._config_latex_tool(self, lt) if not 'qcircuit' in lt.packages: lt.packages.append('qcircuit')
def __init__(self, eps): ''' P_success(eps) ''' Operation.__init__(self, P_SUCCESS, eps)
def formatted(self, format_type, fence=True): if format_type == STRING: return Operation.formatted(format_type, fence=False) elif format_type == LATEX: return r'\left[' + self.operands.formatted(format_type) + '\right]'
def __init__(self, mapExpr): Operation.__init__(self, DOMAIN, [mapExpr])
from proveit.basiclogic import Forall, Equals, In, TRUE, Iff, Implies, And from mappingOps import Domain, CoDomain from proveit.common import f, g, x, y, Q, fx, fy, gx, Qx, Qy fxMap = Lambda(x, fx) # x -> f(x) fxGivenQxMap = Lambda(x, fx, Qx) # x -> f(x) | Q(x) gxGivenQxMap = Lambda(x, gx, Qx) # x -> g(x) | Q(x) fDomain_eq_gDomain = Equals(Domain(f), Domain(g)) # Domain(f) = Domain(g) fx_eq_gx = Equals(fx, gx) # f(x) = g(x) x_in_fDomain = In(x, Domain(f)) # x in Domain(f) f_eq_g = Equals(f, g) # f = g mappingAxioms = Axioms(__package__, locals()) mapApplication = Forall((f, Q), Forall(y, Equals(Operation(fxGivenQxMap, y), fy), Qy)) # forall_{f} [x -> f(x)] = [x -> f(x) | TRUE] lambdaOverAllDef = Forall(f, Equals(Lambda(x, fx), Lambda(x, fx, TRUE))) # forall_{f, Q} forall_{y} y in Domain(x -> f(x) | Q(x)) <=> Q(y) lambdaDomainDef = Forall((f, Q), Forall(y, Iff(In(y, Domain(fxGivenQxMap)), Qy))) # forall_{f, g} [Domain(f) = Domain(g) and forall_{x in Domain(f)} f(x) = g(x)] => (f = g)} mapIsAsMapDoes = Forall( (f, g), Implies(And(fDomain_eq_gDomain, Forall(x, fx_eq_gx, x_in_fDomain)), f_eq_g)) mappingAxioms.finish(locals())
def __init__(self, ket): Operation.__init__(self, MEAS, ket) self.ket = ket
def __init__(self, gate_operation): ''' Create a quantum circuit gate performing the given operation. ''' Operation.__init__(self, GATE, gate_operation) self.gate_operation = gate_operation
if isinstance(gate, ImplicitIdentities): subMap[gate] = [I]*(width-column.min_nrows+1) fixImplicitIdentityWidths(subbed_expr) return Forall.specialize(self, subMap) """ class QuantumCircuitException(): def __init__(self, msg): self.msg = msg def __str__(self): return self.msg """ class Gates(Operation): ''' Represents a column of gate operations in parallel on one or more qubits. ''' def __init__(self, *gates): Operation.__init__(self, GATE, gates) self.gates = gates = self.etcExpr self.gate_min_widths = [gate.size if hasattr(gate, 'width') else 1 for gate in gates] self.min_nrows = sum(self.gate_min_widths) self.multivar_rows = {row for row, gate in enumerate(gates) if isinstance(gate, MultiVariable)} num_multivars = len(self.multivar_rows) # a row may only be expandable if it is the only MultiVariable of the column self.expandable = (num_multivars == 1) self.expandable_row = list(self.multivar_rows)[0] if self.expandable else None
def __init__(self, event, random_variable): Operation.__init__(self, PROB, [event, random_variable]) self.event = event self.random_variable = random_variable
def __init__(self, eps): ''' P_fail(eps) ''' Operation.__init__(self, P_FAIL, eps)
def __init__(self, label): Operation.__init__(self, BRA, label) self.label = label
def _config_latex_tool(self, lt): Operation._config_latex_tool(self, lt) if not 'mathtools' in lt.packages: lt.packages.append('mathtools')
def __init__(self, label, size): Operation.__init__(self, REGISTER_KET, [label, size]) self.label = label self.size = size # size of the register
def __init__(self, number): ''' Create a multi-wire. ''' Operation.__init__(self, MULTI_WIRE, number) self.number = number
def __init__(self, U, t): ''' Phase estimator circuit for Unitary U and t register qubits. ''' Operation.__init__(self, PHASE_ESTIMATION, (U, t))
def __init__(self, angle1, angle2): Operation.__init__(self, ANGULAR_DIFFERENCE, (angle1, angle2)) self.angle1 = angle1 self.angle2 = angle2
def formatted(self, formatType, fence=False): formattedNumber = self.number.formatted(formatType, fence=False) if formatType == LATEX: return r'/^{' + formattedNumber + r'} \qw' else: return Operation.formatted(self, formatType, fence)
def __init__(self, n): ''' QFT circuit for n qubits. ''' Operation.__init__(self, INV_FT, n) self.nqubits = n
def __init__(self, map_expr): Operation.__init__(self, CODOMAIN, [map_expr])