def generate_circuit_by_depth(L, D, W, gate_maker):
    """
    This function this generates an IBM circuit.
    It is called with the following inputs:
    L, the number of bits per batch,
    D, the depth of the circuit as defined by IBM,
    W, the number of input 'wires' (batch inputs taken) in the circuit, and
    gate_maker, the function used to produce each gate.
    """
    # Create the circuit:
    circuit = ic.IBMCircuit(L)
    # Create W input wires:
    wires = [iw.IBMInputWire("".join(("W", str(wire_ind))), circuit)
             for wire_ind in xrange(W)]
    circuit.set_input_wires(wires)
    ultimate_level = wires # the last level created
    penultimate_level = [] # the second-to-last level created
    # Keep track of the smallest gate depth at the last level:
    min_depth = 0
    # Maintain a list of gates at depth D:
    depth_D_gates = []
    # Maintain a list of gates between depth D and D+1, not including D:
    depth_around_D_gates = []
    # Initialize the global gate counter, which acts as the unique numerical id
    # of each gate:
    unique_gate_num = W
    while (min_depth <= D):
        new_level = []
        for gate_index in range(W): # create W new gates
            new_gate = gate_maker(L,
                                  ultimate_level,
                                  penultimate_level,
                                  "".join(["G", str(unique_gate_num)]),
                                  circuit)
            # If the new gate has depth D, add it to depth_D_gates:
            if (new_gate.get_depth() == D): 
                depth_D_gates.append(new_gate)
            # If the new gate has D < depth <= D+1, add it to
            # depth_around_D_gates:
            if ((new_gate.get_depth() > D) and (new_gate.get_depth() < D+1)):
                depth_around_D_gates.append(new_gate)
            # Add the new gate to the new level:
            new_level.append(new_gate)
            # Increment the unique gate number:
            unique_gate_num += 1
        # Increment the smallest gate depth at the last level as needed:
        min_depth = min(gate.get_depth() for gate in new_level)
        # Update the ultimate_level and penultimate_level pointers:
        penultimate_level = ultimate_level
        ultimate_level = new_level
    # If there is at least one gate of depth exactly D, select the output
    # gate from among such gates at random. Otherwise, select the output
    # gate from among gates between depth D and D+1.
    if(len(depth_D_gates) > 0):
        output_gate = sr.choice(depth_D_gates)
    else:
        output_gate = sr.choice(depth_around_D_gates)
    circuit.set_output_gate(output_gate)
    return circuit
예제 #2
0
def generate_circuit_by_depth(B, L, D, W, gate_maker):
    """
    This function this generates an IBM circuit.
    It is called with the following inputs:
    L, the number of bits per batch,
    D, the depth of the circuit as defined by IBM,
    W, the number of input 'wires' (batch inputs taken) in the circuit, and
    gate_maker, the function used to produce each gate.
    """
    # Create the circuit:
    circuit = ic.IBMCircuit(L)
    # Create W input wires:
    wires = [
        iw.IBMInputWire("".join(("W", str(wire_ind))), circuit)
        for wire_ind in xrange(W)
    ]
    circuit.set_input_wires(wires)
    ultimate_level = wires  # the last level created
    penultimate_level = []  # the second-to-last level created
    # Keep track of the smallest gate depth at the last level:
    min_depth = 0
    # Maintain a list of gates at depth D:
    depth_D_gates = []
    # Maintain a list of gates between depth D and D+1, not including D:
    depth_around_D_gates = []
    # Initialize the global gate counter, which acts as the unique numerical id
    # of each gate:
    unique_gate_num = W
    while (min_depth <= D):
        new_level = []
        for gate_index in range(W):  # create W new gates
            new_gate = gate_maker(B, L, ultimate_level, penultimate_level,
                                  "".join(["G",
                                           str(unique_gate_num)]), circuit)
            # If the new gate has depth D, add it to depth_D_gates:
            if (new_gate.get_depth() == D):
                depth_D_gates.append(new_gate)
            # If the new gate has D < depth <= D+1, add it to
            # depth_around_D_gates:
            if ((new_gate.get_depth() > D) and (new_gate.get_depth() < D + 1)):
                depth_around_D_gates.append(new_gate)
            # Add the new gate to the new level:
            new_level.append(new_gate)
            # Increment the unique gate number:
            unique_gate_num += 1
        # Increment the smallest gate depth at the last level as needed:
        min_depth = min(gate.get_depth() for gate in new_level)
        # Update the ultimate_level and penultimate_level pointers:
        penultimate_level = ultimate_level
        ultimate_level = new_level
    # If there is at least one gate of depth exactly D, select the output
    # gate from among such gates at random. Otherwise, select the output
    # gate from among gates between depth D and D+1.
    if (len(depth_D_gates) > 0):
        output_gate = sr.choice(depth_D_gates)
    else:
        output_gate = sr.choice(depth_around_D_gates)
    circuit.set_output_gate(output_gate)
    return circuit
예제 #3
0
def make_random_gate(B, L, ultimate_level, penultimate_level, gate_name,
                     circuit):
    """Creates a random gate with uniformly distributed type."""
    gate_type = sr.choice(
        [g_type for g_type in GATE_TYPES.numbers_generator()])
    generate = TEST_TYPE_TO_GATE_MAKER[gate_type]
    return generate(B, L, ultimate_level, penultimate_level, gate_name,
                    circuit)
예제 #4
0
def generate_circuit_by_level(B, L, num_levels, W, gate_maker):
    """
    This function this generates a random IBM circuit with num_levels instead
    of depth specified.
    It is called with the following inputs:
    L, the number of bits per batch,
    num_levels, the the number of levels in the circuit,
    W, the number of input 'wires' (batch inputs taken) in the circuit, and
    gate_maker, the function used to produce each gate.
    """
    # Create the circuit:
    circuit = ic.IBMCircuit(L)
    # Create W input wires:
    wires = [
        iw.IBMInputWire("".join(("W", str(wire_ind))), circuit)
        for wire_ind in xrange(W)
    ]
    circuit.set_input_wires(wires)
    ultimate_level = wires  # the last level created
    penultimate_level = []  # the second-to-last level created
    # Initialize the global gate counter, which acts as the unique numerical id
    # of each gate:
    unique_gate_num = W
    for level in xrange(num_levels):
        new_level = []
        for gate_index in xrange(W):  # create W new gates
            new_gate = gate_maker(B, L, ultimate_level, penultimate_level,
                                  "".join(["G",
                                           str(unique_gate_num)]), circuit)
            # Add the new gate to the new level:
            new_level.append(new_gate)
            # Increment the unique gate number:
            unique_gate_num += 1
        # Update the ultimate_level and penultimate_level pointers:
        penultimate_level = ultimate_level
        ultimate_level = new_level
    # Select the output gate from the last level:
    output_gate = sr.choice(ultimate_level)
    circuit.set_output_gate(output_gate)
    return circuit
def generate_circuit_by_level(L, num_levels, W, gate_maker):
    """
    This function this generates a random IBM circuit with num_levels instead
    of depth specified.
    It is called with the following inputs:
    L, the number of bits per batch,
    num_levels, the the number of levels in the circuit,
    W, the number of input 'wires' (batch inputs taken) in the circuit, and
    gate_maker, the function used to produce each gate.
    """
    # Create the circuit:
    circuit = ic.IBMCircuit(L)
    # Create W input wires:
    wires = [iw.IBMInputWire("".join(("W",str(wire_ind))), circuit)
             for wire_ind in xrange(W)]
    circuit.set_input_wires(wires)
    ultimate_level = wires # the last level created
    penultimate_level = [] # the second-to-last level created
    # Initialize the global gate counter, which acts as the unique numerical id
    # of each gate:
    unique_gate_num = W
    for level in xrange(num_levels):
        new_level = []
        for gate_index in xrange(W): # create W new gates
            new_gate = gate_maker(L,
                                  ultimate_level,
                                  penultimate_level,
                                  "".join(["G", str(unique_gate_num)]),
                                  circuit)
            # Add the new gate to the new level:
            new_level.append(new_gate)
            # Increment the unique gate number:
            unique_gate_num += 1
        # Update the ultimate_level and penultimate_level pointers:
        penultimate_level = ultimate_level
        ultimate_level = new_level
    # Select the output gate from the last level:
    output_gate = sr.choice(ultimate_level)
    circuit.set_output_gate(output_gate)
    return circuit
 def generate(self):
     """Populates the circuit, input and output files with a circuit, an
     input, and the corresponding output with the appropriate parameters."""
     # create the header and write it to the circuit file:
     header_string = self._create_circuit_header()
     # create the input wires and write the inputs to the input file:
     input_wires = self._create_input_wires()
     # set set of all circuit objects already created:
     levels = [input_wires]
     # initialize the global gate counter, which acts as the unique numerical
     # id of each gate:
     unique_gate_num_gen = itertools.count()
     # for each level:
     for level_index in xrange(self._D):
         # Create the list of gates at this level:
         this_level = [None] * self._W
         for gate_ind in xrange(self._W):
             displayname = "".join(["G",str(unique_gate_num_gen.next())])
             # make the new gate:
             new_gate = self._gate_maker(levels, displayname)
             new_gate_output = int(sr.getrandbits(1))
             new_gate.balance(new_gate_output)
             # add this gate to our list of gates at this level:
             this_level[gate_ind] = new_gate
         # set things up for the next level:
         ultimate_level = this_level
         levels.append(this_level)
     output_gate = sr.choice(levels[-1])
     output_gate.set_name("output_gate")
     # choose a random output, and write it to the output file:
     output = int(sr.getrandbits(1))
     self._output_file.write(str(output))
     # balance the output gate with respect to the chosen output:
     output_gate.balance(output)
     circ = sc.StealthCircuit(input_wires, output_gate)
     # write the circuit to the circuit file:
     self._circuit_file.write(circ.display())
def make_random_gate(L, ultimate_level, penultimate_level, gate_name, circuit):
    """Creates a random gate with uniformly distributed type."""
    gate_type = sr.choice([g_type for g_type in GATE_TYPES.numbers_generator()])
    generate = TEST_TYPE_TO_GATE_MAKER[gate_type]
    return generate(L, ultimate_level, penultimate_level, gate_name, circuit)