#๐Ÿ”’ Need Help with converting the function to use dicts instead of if-else blocks

69 messages ยท Page 1 of 1 (latest)

full linden
crimson yarrowBOT
#

@full linden

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

full linden
#

@gray skiff

#

Thank you in advance for the help.

#

So, I have this code, fully functional, but it's just sooo long with all the if-else blocks, and would like to make it as short and simple as possible, more pythonic in a sense.

#

Right now, all the dict approaches I tried become massive, and just make the code harder to read than making it shorter.

gray skiff
#

the first low-hanging fruit i noticed is this series of if statements here

#

in which, you could use a dict

full linden
#

Case in point

gray skiff
#

give me a sec to type it out

full linden
#

Of course, please take your time.

gray skiff
#

wait hold on

full linden
#

Yes?

gray skiff
#

what are circ.X, circ.Y, etc.?

#

like their types

#

i need to know if they are hashable

full linden
#

Oh, they're methods.

#

Actually, they could be treated as objects as well.

#

Like I can use them as an object.

gray skiff
#

yep, methods are just objects in python

#

so they're hashable

full linden
#
class _PauliX(Pauli, common_gates.XPowGate):
    def __init__(self):
        Pauli.__init__(self, index=0, name='X')
        common_gates.XPowGate.__init__(self, exponent=1.0)

    def __pow__(self, exponent: 'cirq.TParamVal') -> common_gates.XPowGate:
        return common_gates.XPowGate(exponent=exponent) if exponent != 1 else _PauliX()

    def _with_exponent(self, exponent: 'cirq.TParamVal') -> common_gates.XPowGate:
        return self.__pow__(exponent)

    @classmethod
    def _from_json_dict_(cls, exponent, global_shift, **kwargs):
        assert global_shift == 0
        assert exponent == 1
        return Pauli._XYZ[0]

    @property
    def basis(self) -> Dict[int, '_XEigenState']:
        from cirq.value.product_state import _XEigenState

        return {+1: _XEigenState(+1), -1: _XEigenState(-1)}
#
X = _PauliX()
gray skiff
#

you could do something like this pattern

#

if_true is a mapping from your parameters['sub_gate'] field to functions

#

you could also apply that to a few of the other if/else's below it

full linden
#

I am sort of aiming for sth like what I did here:

def convert(self,
                circuit_framework: Type[Circuit]) -> Circuit:
        converted_circuit = circuit_framework(self.num_qubits, self.num_clbits)

        gate_mapping: dict[str, Callable] = {
            'RX': converted_circuit.RX,
            'RY': converted_circuit.RY,
            'RZ': converted_circuit.RZ,
            'H': converted_circuit.H,
            'X': converted_circuit.X,
            'Y': converted_circuit.Y,
            'Z': converted_circuit.Z,
            'S': converted_circuit.S,
            'T': converted_circuit.T,
            'U3': converted_circuit.U3,
            'SWAP': converted_circuit.SWAP,
            'CX': converted_circuit.CX,
            'CY': converted_circuit.CY,
            'CZ': converted_circuit.CZ,
            'CH': converted_circuit.CH,
            'CS': converted_circuit.CS,
            'CT': converted_circuit.CT,
            'CRX': converted_circuit.CRX,
            'CRY': converted_circuit.CRY,
            'CRZ': converted_circuit.CRZ,
            'CU3': converted_circuit.CU3,
            'CSWAP': converted_circuit.CSWAP,
            'MCX': converted_circuit.MCX,
            'MCY': converted_circuit.MCY,
            'MCZ': converted_circuit.MCZ,
            'MCH': converted_circuit.MCH,
            'MCS': converted_circuit.MCS,
            'MCT': converted_circuit.MCT,
            'MCRX': converted_circuit.MCRX,
            'MCRY': converted_circuit.MCRY,
            'MCRZ': converted_circuit.MCRZ,
            'MCU3': converted_circuit.MCU3,
            'MCSWAP': converted_circuit.MCSWAP,
            'GlobalPhase': converted_circuit.GlobalPhase,
            'measure': converted_circuit.measure
        }

        for gate_info in self.circuit_log:

            gate_name = gate_info['gate']

            gate_info = dict(list(gate_info.items())[1:])

            gate_mapping[gate_name](**gate_info)

        return converted_circuit
#

All of this is to basically avoid having if-else blocks.

gray skiff
#

Yes, Python doesnt have Rust's much cleaner match which would be a perfect application for this

#

Which is unfortunate

full linden
#

But I am also learning what is considered "pythonic", so please let me know if the one you shown is considered good practice and I can adapt that.

full linden
gray skiff
#

"Pythonic" is subjective but it generally just means doing things in a way that takes advantage of the language's unique characteristic

#

characteristics*

full linden
#

Yeah.

gray skiff
#

for example, functions are first class objects

#

So since you have a long chain of if/else's where you just call different functions, have a mapping from conditions to functions instead

#

Which you've already done

#

My code example earlier simply replicates the additional logic you have of also checking for the len(parameters['control_qid_shape'])

full linden
#

Yeah, but in this one that we're talking about now issue is the inconsistency of the parameters passed and the nested ifs.

gray skiff
#

But it follows the same general pattern that you've shown in that latest codeblock

full linden
full linden
#

or outside?

#

I am sort of considering using lambda to define the dict outside once, instead of defining it everytime inside the loop.

gray skiff
#

It's in the same context as everything under your "elif gate_type == 'ControlledGate'"

#

So it's inside the loop

full linden
#

I see.

#

Would using lambda help?

#

To have the mapping dict outside the loop.

gray skiff
#

I don't see why you can't already have the mapping dict outside the loop?

#

circuit already exists before the loop, right?

full linden
#

Like

x = 1

vs

for _ in range(10):
  x = 1
gray skiff
#

Yes, if it were inside the loop

#

But I'm saying, you can have it outside the loop already

#

With how your code is

#

given that circuit exists outside the loop

#

So everything you need to map to, i.e. circuit's methods, already exist

#

For this codeblock, I don't think you need a mapping dict

#

It's small, and you have one outlier case being ZPowGate which would be awkward having to have an if-statement separate from the mapping since there's no way to cleanly fit the logic for ZPowGate inside the mapping without defining an external function (unnecessary complexity) or having an obnoxiously long lambda

#

Anyway, seems you have Opal helping you already

#

I'm going to have dinner

full linden
full linden
#

Thank you again!

crimson yarrowBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.