def run_exp(
    method='qrac',
    epochs=300,
    positive_factor=1 / 3,
    depth=4,
    seed=10598,
    reg=0.,
    model_directory=None,
    result_directory=None,
    real_device=False,
):
    assert method in [
        'qrac', 'qrac_zz', 'te', 'te_zz', 'zz_dis', 'zz_dis_cont'
    ], f"method {method} not exist"

    if model_directory is None:
        model_directory = f'models/Titanic_{method}_{epochs}_{positive_factor}_{depth}_{seed}_{reg}_model'
    if result_directory is None:
        result_directory = f'results/Titanic_{method}_{epochs}_{positive_factor}_{depth}_{seed}_{reg}_result'

    all_discrete = method in ['qrac', 'te', 'zz_dis']

    df_train, _, y_train, _ = load_titanic_pd('data/Titanic_train.csv',
                                              'data/Titanic_test.csv',
                                              as_category=all_discrete)

    # Get mvp column
    mvp_col = ['Sex', 'Age', 'Pclass', 'Fare']
    df_train = df_train[mvp_col]
    vqc_gen = None
    feature_map = None
    var_form = None
    X_train = None
    if method in ['zz_dis']:
        X_train = df_train.values
        feature_map = ZZFeatureMap(4)
        var_form = RYRZ(4, depth=depth)
        vqc_gen = VQC

    if method in ['zz_dis_cont']:
        df_train['Fare'] = np.log(df_train['Fare'] + 1)
        df_train['Age'] = df_train['Age'] / 60
        X_train = df_train.values
        feature_map = ZZFeatureMap(4)
        var_form = RYRZ(4, depth=depth)
        vqc_gen = VQC

    if method in ['qrac', 'te']:
        X_train = binary_encoder(df_train.values)
        print(X_train)
        num_qubit = len(X_train[0]) // 3
        if method == 'qrac':
            feature_map = CustomFeatureMap('ALL3in1', 1, num_qubit)
            var_form = RYRZ(num_qubit, depth=depth)
            vqc_gen = VQC
        if method == 'te':
            feature_map = QuantumCircuit(num_qubit)
            var_form = MyRYRZ(num_qubit, depth=depth)
            vqc_gen = MyVQC

    if method in ['qrac_zz']:
        df_train['Fare'] = np.log(df_train['Fare'] + 1)
        df_train['Age'] = df_train['Age'] / 60
        X_train_num = U3gate_input_encoder(df_train[['Sex', 'Pclass']].values)
        X_train_con = df_train[['Age', 'Fare']].values
        X_train = np.concatenate([X_train_con, X_train_num], axis=1)

        X = [Parameter(f'x[{i}]') for i in range(X_train_num.shape[1])]
        qr = QuantumRegister(1, 'cat')
        qc = QuantumCircuit(qr)

        for i in range(1):
            qc.u3(X[2 * i], X[2 * i + 1], 0, i)
        feature_map_cat = qc

        X1 = Parameter('x[2]')
        X2 = Parameter('x[3]')
        feature_map_con = ZZFeatureMap(2)
        feature_map_con = feature_map_con.assign_parameters([X1, X2])

        feature_map = feature_map_con.combine(feature_map_cat)
        var_form = RYRZ(3, depth=depth)
        vqc_gen = VQC

    if method in ['te_zz']:
        df_train['Fare'] = np.log(df_train['Fare'] + 1)
        df_train['Age'] = df_train['Age'] / 60
        X_train_num = binary_encoder(df_train[['Sex', 'Pclass']].values)
        X_train_con = df_train[['Age', 'Fare']].values
        print(X_train_num[:, None])
        print(X_train_con)

        X_train = np.array([[x, y] for x, y in zip(X_train_num, X_train_con)])

        X1 = Parameter('x[0]')
        X2 = Parameter('x[1]')
        feature_map_con = ZZFeatureMap(2)
        feature_map_con = feature_map_con.assign_parameters([X1, X2])

        qr = QuantumRegister(1, 'cat')
        feature_map_num = QuantumCircuit(qr)

        feature_map = feature_map_num.combine(feature_map_con)
        var_form = MyRYRZ_zz(1, 2, depth=depth)
        vqc_gen = MyVQC_zz

    assert feature_map is not None, "Feature map is none"
    assert var_form is not None, "Varform is none"

    if real_device:
        # Please fix these line...
        provider = IBMQ.get_provider()
        backend = provider.get_backend('ibmq_london')
    else:
        backend = QasmSimulator({"method": "statevector_gpu"})

    def optimizer_gen():
        return SPSA(epochs)

    result = kfold_vqc(feature_map,
                       var_form,
                       backend,
                       optimizer_gen,
                       seed,
                       X_train,
                       y_train,
                       model_directory=model_directory,
                       result_directory=result_directory,
                       k=4,
                       positivedata_duplicate_ratio=positive_factor,
                       vqc_gen=vqc_gen)

    return_result = {
        'train_acc': result['Training accuracies (mean)'][-1],
        'train_f1': result['Training F1 scores (mean)'][-1],
        'test_acc': result['Test accuracies (mean)'][-1],
        'test_f1': result['Test F1 scores (mean)'][-1]
    }

    return return_result
from sklearn import preprocessing

iris = datasets.load_iris()

# load iris and normalise
x = preprocessing.normalize(iris.data)
x1_train = x[0:49, :]  # class A
x2_train = x[50:99, :]  # class B
training_input = {'A': x1_train, 'B': x2_train}
class_labels = ['A', 'B']
blocks = 1
sv = Statevector.from_label('0' * n)
# circuit = QuantumCircuit(n)
feature_map = ZZFeatureMap(n, reps=2, entanglement='full')
var_form = RealAmplitudes(n, reps=blocks, entanglement='full')
circuit = feature_map.combine(var_form)


def get_data_dict(params, x):
    """Get the parameters dict for the circuit"""
    parameters = {}
    for i, p in enumerate(feature_map.ordered_parameters):
        parameters[p] = x[i]
    for i, p in enumerate(var_form.ordered_parameters):
        parameters[p] = params[i]
    return parameters


def assign_label(bit_string, class_labels):
    hamming_weight = sum([int(k) for k in list(bit_string)])
    is_odd_parity = hamming_weight & 1