# created by jialin
# translate a DAG into a spectre netlist file

import os
import sys
import string
import random
import numpy as np

def get_node_info(x, idx):
    instance_head = []
    node = []
    instance = []
    instance_val = []
    unit = []
    bound = []
    additional_node = []
    additional_ins_head = []
    additional_ins = []
    additional_ins_val = []
    additional_ins_unit = []
    additional_ins_bound = []
    if x == 0:
        instance_head = []
        node = []
        instance = []
        instance_val = []
        unit = []
        bound = []
        additional_node = []
        additional_ins_head = []
        additional_ins = []
        additional_ins_val = []
        additional_ins_unit = []
        additional_ins_bound = []
    elif x == 1:  # R
        instance_head = ['R']
        node = [0, 1]
        instance = []
        instance_val = ['r']
        unit = ['*1meg']
        bound = ['1']
        additional_node = []
        additional_ins_head = []
        additional_ins = []
        additional_ins_val = []
        additional_ins_unit = []
        additional_ins_bound = []
    elif x == 2:  # C
        instance_head = ['C']
        node = [0, 1]
        instance = []
        instance_val = ['c']
        unit = ['*1p']
        bound = ['10']
        additional_node = []
        additional_ins_head = []
        additional_ins = []
        additional_ins_val = []
        additional_ins_unit = []
        additional_ins_bound = []
    elif x == 3:  # RC parallel
        instance_head = ['R', 'C']
        node = [0, 1]
        instance = []
        instance_val = ['r', 'c']
        unit = ['*1meg', '*1p']
        bound = ['1', '10']
        additional_node = []
        additional_ins_head = []
        additional_ins = []
        additional_ins_val = []
        additional_ins_unit = []
        additional_ins_bound = []
    elif x == 4:  # RC series
        instance_head = ['R', 'C']
        node = [0, 1]
        instance = []
        instance_val = ['r', 'c']
        unit = ['*1meg', '*1p']
        bound = ['10', '10']
        additional_node = [2]
        additional_ins_head = []
        additional_ins = []
        additional_ins_val = []
        additional_ins_unit = []
        additional_ins_bound = []
    elif x == 5:  # Feedforward +gm
        instance_head = ['X']
        node = [0, 1]
        instance = ['gm+']
        additional_node = [0]
        additional_ins_head = ['R', 'C']
        # additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        if idx <= 1:
            instance_val = ['wn', 'wp', 'wb']
            unit = ['*1u', '*1u', '*1u']
            bound = ['50', '50', '50']
        else:
            instance_val = ['wp', 'wb']
            unit = ['*1u', '*1u']
            bound = ['50', '50']
    elif x == 6:  # Feedforward -gm
        instance_head = ['X']
        node = [0, 1]
        instance = ['gm-']
        additional_node = [0]
        additional_ins_head = ['R', 'C']
        # additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        if idx <= 1:
            instance_val = ['wn', 'wp', 'wb']
            unit = ['*1u', '*1u', '*1u']
            bound = ['50', '50', '50']
        else:
            instance_val = ['wp', 'wn']
            unit = ['*1u', '*1u']
            bound = ['50', '50']
    ###
    elif x == 7:  # R&5 series
        instance_head = ['X', 'R']
        node = [0, 1]
        instance = ['gm+']
        additional_node = [2]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        if idx <= 1:
            instance_val = ['wn', 'wp', 'wb', 'r']
            unit = ['*1u', '*1u', '*1u', '*1meg']
            bound = ['50', '50', '50', '10']
        else:
            instance_val = ['wp', 'wb', 'r']
            unit = ['*1u', '*1u', '*1meg']
            bound = ['50', '50', '10']
    elif x == 8:  # C&5 series
        instance_head = ['X', 'C']
        node = [0, 1]
        instance = ['gm+']
        additional_node = [2]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        if idx <= 1:
            instance_val = ['wn', 'wp', 'wb', 'c']
            unit = ['*1u', '*1u', '*1u', '*1p']
            bound = ['50', '50', '50', '10']
        else:
            instance_val = ['wp', 'wb', 'c']
            unit = ['*1u', '*1u', '*1p']
            bound = ['50', '50', '10']
    elif x == 9:  # R&6 series
        instance_head = ['X', 'R']
        node = [0, 1]
        instance = ['gm-']
        additional_node = [2]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        if idx <= 1:
            instance_val = ['wn', 'wp', 'wb', 'r']
            unit = ['*1u', '*1u', '*1u', '*1meg']
            bound = ['50', '50', '50', '10']
        else:
            instance_val = ['wp', 'wn', 'r']
            unit = ['*1u', '*1u', '*1meg']
            bound = ['50', '50', '10']
    elif x == 10:  # C&6 series
        instance_head = ['X', 'C']
        node = [0, 1]
        instance = ['gm-']
        additional_node = [2]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        if idx <= 1:
            instance_val = ['wn', 'wp', 'wb', 'c']
            unit = ['*1u', '*1u', '*1u', '*1p']
            bound = ['50', '50', '50', '10']
        else:
            instance_val = ['wp', 'wn', 'c']
            unit = ['*1u', '*1u', '*1meg']
            bound = ['50', '50', '10']
    elif x == 11:  # R&5 parallel
        instance_head = ['X', 'R']
        node = [0, 1]
        instance = ['gm+']
        additional_node = [1]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        if idx <= 1:
            instance_val = ['wn', 'wp', 'wb', 'r']
            unit = ['*1u', '*1u', '*1u', '*1meg']
            bound = ['50', '50', '50', '10']
        else:
            instance_val = ['wp', 'wb', 'r']
            unit = ['*1u', '*1u', '*1meg']
            bound = ['50', '50', '10']
    elif x == 12:  # C&5 parallel
        instance_head = ['X', 'C']
        node = [0, 1]
        instance = ['gm+']
        additional_node = [1]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        if idx <= 1:
            instance_val = ['wn', 'wp', 'wb', 'c']
            unit = ['*1u', '*1u', '*1u', '*1p']
            bound = ['50', '50', '50', '10']
        else:
            instance_val = ['wp', 'wb', 'c']
            unit = ['*1u', '*1u', '*1p']
            bound = ['50', '50', '10']
    elif x == 13:  # R&6 parallel
        instance_head = ['X', 'R']
        node = [0, 1]
        instance = ['gm-']
        additional_node = [1]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        if idx <= 1:
            instance_val = ['wn', 'wp', 'wb', 'r']
            unit = ['*1u', '*1u', '*1u', '*1meg']
            bound = ['50', '50', '50', '10']
        else:
            instance_val = ['wp', 'wn', 'r']
            unit = ['*1u', '*1u', '*1meg']
            bound = ['50', '50', '10']
    elif x == 14:  # C&6 parallel
        instance_head = ['X', 'C']
        node = [0, 1]
        instance = ['gm-']
        additional_node = [1]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        if idx <= 1:
            instance_val = ['wn', 'wp', 'wb', 'c']
            unit = ['*1u', '*1u', '*1u', '*1p']
            bound = ['50', '50', '50', '10']
        else:
            instance_val = ['wp', 'wn', 'c']
            unit = ['*1u', '*1u', '*1p']
            bound = ['50', '50', '10']
    ###
    elif x == 15:  # Feedback +gm
        instance_head = ['X']
        node = [1, 0]
        instance = ['gm+']
        instance_val = ['wp', 'wb']
        unit = ['*1u', '*1u']
        bound = ['50', '50']
        additional_node = [1]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
    elif x == 16:  # Feedback -gm
        instance_head = ['X']
        node = [1, 0]
        instance = ['gm-']
        instance_val = ['wp', 'wn']
        unit = ['*1u', '*1u']
        bound = ['50', '50']
        additional_node = [0]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
    elif x == 17:  # R&15 parallel
        instance_head = ['R', 'X']
        node = [1, 0]
        instance = ['gm+']
        additional_node = [0]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        instance_val = ['r', 'wp', 'wb']
        unit = ['*1meg', '*1u', '*1u']
        bound = ['10', '50', '50']
    elif x == 18:  # R&15 series
        instance_head = ['R', 'X']
        node = [1, 0]
        instance = ['gm+']
        additional_node = [2]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        instance_val = ['r', 'wp', 'wb']
        unit = ['*1meg', '*1u', '*1u']
        bound = ['10', '50', '50']
    elif x == 19:  # C&15 parallel
        instance_head = ['C', 'X']
        node = [1, 0]
        instance = ['gm+']
        additional_node = [0]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        instance_val = ['c', 'wp', 'wb']
        unit = ['*1p', '*1u', '*1u']
        bound = ['10', '50', '50']
    elif x == 20:  # C&15 series
        instance_head = ['C', 'X']
        node = [1, 0]
        instance = ['gm+']
        additional_node = [2]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        instance_val = ['c', 'wp', 'wb']
        unit = ['*1p', '*1u', '*1u']
        bound = ['10', '50', '50']
    elif x == 21:  # R&16 parallel
        instance_head = ['R', 'X']
        node = [1, 0]
        instance = ['gm-']
        instance_val = ['r', 'gm']
        unit = ['*1M', '*-1m']
        bound = ['10', '10']
        additional_node = [0]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        instance_val = ['r', 'wp', 'wn']
        unit = ['*1meg', '*1u', '*1u']
        bound = ['10', '50', '50']
    elif x == 22:  # R&16 series
        instance_head = ['R', 'X']
        node = [1, 0]
        instance = ['gm-']
        additional_node = [2]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        instance_val = ['r', 'wp', 'wn']
        unit = ['*1meg', '*1u', '*1u']
        bound = ['10', '50', '50']
    elif x == 23:  # C&16 parallel
        instance_head = ['C', 'X']
        node = [1, 0]
        instance = ['gm-']
        additional_node = [0]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        instance_val = ['c', 'wp', 'wn']
        unit = ['*1p', '*1u', '*1u']
        bound = ['10', '50', '50']
    elif x == 24:  # C&16 series
        instance_head = ['C', 'X']
        node = [1, 0]
        instance = ['gm-']
        additional_node = [2]
        additional_ins_head = ['R', 'C']
        additional_ins = ['resistor', 'capacitor']
        additional_ins_val = ['r', 'c']
        additional_ins_unit = ['*1K', '*1p']
        additional_ins_bound = ['80', '1']
        instance_val = ['c', 'wp', 'wn']
        unit = ['*1p', '*1u', '*1u']
        bound = ['10', '50', '50']

    return instance_head, node, instance, instance_val, unit, bound, additional_node, additional_ins_head, additional_ins, additional_ins_val, additional_ins_unit, additional_ins_bound

def amp_generator(topo_vector):
    '''
    os.chdir('tmp_circuit')
    os.system('mkdir ' + design_id)
    os.chdir(design_id)
    os.system('mkdir circuit')
    os.chdir('circuit')
    os.system('mkdir netlist')
    os.chdir('../../..')

    tmp_conf = open('./tmp_circuit/' + design_id + '/tmp.conf', 'w')
    netlist = open('./tmp_circuit/' + design_id + '/circuit/netlist/netlist', 'w')
    '''
    tmp_conf = open('./conf', 'w')
    netlist = open('./opamp.sp', 'w')
    # netlist.writelines('V0 (net_vin 0) vsource mag=1 type=sine\n')     # V_source setting
    '''
    netlist.writelines('.title Project: Three-STAGE OPAMP\n')
    netlist.writelines('.LIB "\home\shenjinyi\behavioral_model\sm046005-1j.hspice" typical\n')
    netlist.writelines('.inc \'param\'\n')

    netlist.writelines('.param l=1u\n')
    netlist.writelines('.param Vr=3.3\n')
    netlist.writelines('.param Vc=1.3\n')
    netlist.writelines('.param Vb1=0.9\n')
    netlist.writelines('.param Vb2=2.3\n')
    '''
    netlist.writelines('.inc \'gm+.sp\'\n')
    netlist.writelines('.inc \'gm-.sp\'\n')
    netlist.writelines('.inc \'gm+_middle.sp\'\n')
    netlist.writelines('.inc \'gm-_middle.sp\'\n')
    netlist.writelines('.subckt opamp vp vn out vb1 vb2 vdd\n')

    netlist.writelines('X_vin_1 net_vinp net_vinn net_1 vb1 vdd gm+ wp=wp_in_1*1u wn=wn_in_1*1u wb=wb_in_1*1u\n')
    tmp_conf.writelines('des_var wp_in_1 2 50\n')
    tmp_conf.writelines('des_var wn_in_1 2 50\n')
    tmp_conf.writelines('des_var wb_in_1 2 50\n')
    # netlist.writelines('R_1_0_prs net_1 0 r=rscl_vin_1_prs/g_vin_1*1K\n')
    # tmp_conf.writelines('des_var rscl_vin_1_prs 40 80\n')
    # netlist.writelines('C_1_0_prs net_1 0 c=g_1_2/6.28*5p\n')

    netlist.writelines('X_1_2 net_1 net_2 vb2 vdd gm-_middle wp=wp_1_2*1u wn=wn_1_2*1u\n')
    tmp_conf.writelines('des_var wp_1_2 2 50\n')
    tmp_conf.writelines('des_var wn_1_2 2 50\n')
    # netlist.writelines('R_2_0_prs (net_2 0) resistor r=rscl_1_2_prs/g_1_2*1K\n')
    # tmp_conf.writelines('des_var rscl_1_2_prs 40 80\n')
    # netlist.writelines('C_2_0_prs (net_2 0) capacitor c=g_2_vo/6.28*5p\n')

    netlist.writelines('X_2_vo net_2 net_vo vb1 vdd gm+_middle wp=wp_2_out*1u wb=wb_2_out*1u\n')
    tmp_conf.writelines('des_var wp_2_out 2 50\n')
    tmp_conf.writelines('des_var wb_2_out 2 50\n')
    # netlist.writelines('R_vo_0_prs (net_vo 0) resistor r=rscl_2_vo_prs/g_2_vo*1K\n')
    # tmp_conf.writelines('des_var rscl_2_vo_prs 40 80\n')
    # netlist.writelines('C_vo_0_prs (net_vo 0) capacitor c=c_vo_0_prs*1p\n')
    # tmp_conf.writelines('des_var c_vo_0_prs 0.01 10\n')

    netlist.writelines('R_L net_vo 0 r=0.15meg\n')  # RC load setting
    netlist.writelines('C_L net_vo 0 c=10n\n')

    node_pairs = [['_vin', '_2', '_vin_2'], ['_vin', '_vo', '_vin_vo'], ['_1', '_vo', '_1_vo'], ['_1', '_0', '_1_0'],
                  ['_2', '_0', '_2_0']]

    for idx, node in enumerate(node_pairs):
        x = topo_vector[idx]
        node_pair = node_pairs[idx]
        instance_head, node, instance, instance_val, unit, bound, additional_node, additional_ins_head, additional_ins, additional_ins_val, additional_ins_unit, additional_ins_bound = get_node_info(
            x, idx)
        if x == 0:
            pass
        elif 1 <= x <= 2:
            if idx <= 2:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[node[0]] + ' net' +
                    node_pair[node[1]] + ' ' + instance_val[0] + '=' + instance_val[0] + node_pair[
                        node[0]] + node_pair[node[1]] + unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')
            else:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[node[0]] + ' 0 ' +
                    instance_val[0] + '=' + instance_val[0] + node_pair[node[0]] + node_pair[
                        node[1]] + unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')
        elif x == 3:
            if idx <= 2:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[node[0]] + ' net' +
                    node_pair[node[1]] + ' ' + instance_val[0] + '=' + instance_val[0] + node_pair[
                        node[0]] + node_pair[node[1]] + unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[node[0]] + ' net' +
                    node_pair[node[1]] + ' ' + instance_val[1] + '=' + instance_val[1] + node_pair[
                        node[0]] + node_pair[node[1]] + unit[1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + ' 0.5 ' + bound[1] + '\n')
            else:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[node[0]] + ' 0 ' +
                    instance_val[0] + '=' + instance_val[0] + node_pair[node[0]] + node_pair[
                        node[1]] + unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[node[0]] + ' 0 ' +
                    instance_val[1] + '=' + instance_val[1] + node_pair[node[0]] + node_pair[
                        node[1]] + unit[1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + ' 0.5 ' + bound[1] + '\n')
        elif x == 4:
            if idx <= 2:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' net' + node_pair[
                        node[0]] + ' net' + node_pair[additional_node[0]] + ' ' + instance_val[
                        0] + '=' + instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + unit[
                        0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' 0.01 ' +
                    bound[0] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' net' + node_pair[
                        additional_node[0]] + ' net' + node_pair[node[1]] + ' ' + instance_val[
                        1] + '=' + instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + unit[
                        1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' 0.5 ' + bound[
                        1] + '\n')
            else:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' net' + node_pair[
                        node[0]] + ' net' + node_pair[additional_node[0]] + ' ' + instance_val[
                        0] + '=' + instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + unit[
                        0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' 0.01 ' +
                    bound[0] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' net' + node_pair[
                        additional_node[0]] + ' 0 ' + instance_val[1] + '=' + instance_val[1] +
                    node_pair[additional_node[0]] + node_pair[node[1]] + unit[1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' 0.5 ' + bound[
                        1] + '\n')
        elif x in [15, 16]:
            if x == 15:
                netlist.writelines(instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[
                    node[0]] + ' net' + node_pair[node[1]] + ' vb1 vdd ' + instance[0] + '_middle ' + instance_val[
                                       0] + '=' +
                                   instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + unit[0] + ' ' +
                                   instance_val[1] + '=' +
                                   instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + unit[1] + '\n')
            else:
                netlist.writelines(instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[
                    node[0]] + ' net' + node_pair[node[1]] + ' vb2 vdd ' + instance[0] + '_middle ' + instance_val[
                                       0] + '=' +
                                   instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + unit[0] + ' ' +
                                   instance_val[1] + '=' +
                                   instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + unit[1] + '\n')
            for i in range(len(instance_val)):
                tmp_conf.writelines(
                    'des_var ' + instance_val[i] + node_pair[node[0]] + node_pair[node[1]] + ' 2 ' + bound[
                        i] + '\n')
        elif x in [5, 6]:
            if idx <= 1:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net_vinp net_vinn net' +
                    node_pair[node[1]] + ' vb1 vdd ' + instance[0] + ' ' + instance_val[0] + '=' + instance_val[0] +
                    node_pair[
                        node[0]] + node_pair[node[1]] + unit[0] + ' ' + instance_val[1] + '=' + instance_val[1] +
                    node_pair[
                        node[0]] + node_pair[node[1]] + unit[1] + ' ' + instance_val[2] + '=' + instance_val[2] +
                    node_pair[
                        node[0]] + node_pair[node[1]] + unit[2] + '\n')
            else:
                if x == 5:
                    netlist.writelines(instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[
                        node[0]] + ' net' + node_pair[node[1]] + ' vb1 vdd ' + instance[0] + '_middle ' + instance_val[
                                           0] + '=' +
                                       instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + unit[0] + ' ' +
                                       instance_val[1] + '=' +
                                       instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + unit[1] + '\n')
                else:
                    netlist.writelines(instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[
                        node[0]] + ' net' + node_pair[node[1]] + ' vb2 vdd ' + instance[0] + '_middle ' + instance_val[
                                           0] + '=' +
                                       instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + unit[0] + ' ' +
                                       instance_val[1] + '=' +
                                       instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + unit[1] + '\n')
            for i in range(len(instance_val)):
                tmp_conf.writelines(
                    'des_var ' + instance_val[i] + node_pair[node[0]] + node_pair[node[1]] + ' 2 ' + bound[
                        i] + '\n')
        elif 7 <= x <= 14:
            if 11 <= x <= 14:
                if idx <= 1:
                    netlist.writelines(
                        instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net_vinp net_vinn net' +
                        node_pair[node[1]] + ' vb1 vdd ' + instance[0] + ' ' + instance_val[0] + '=' + instance_val[0] +
                        node_pair[
                            node[0]] + node_pair[node[1]] + unit[0] + ' ' + instance_val[1] + '=' + instance_val[1] +
                        node_pair[
                            node[0]] + node_pair[node[1]] + unit[1] + ' ' + instance_val[2] + '=' + instance_val[2] +
                        node_pair[
                            node[0]] + node_pair[node[1]] + unit[2] + '\n')
                else:
                    if x == 11 or x == 12:
                        netlist.writelines(
                            instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[
                                node[0]] + ' net' + node_pair[node[1]] + ' vb1 vdd ' + instance[0] + '_middle ' +
                            instance_val[
                                0] + '=' +
                            instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + unit[0] + ' ' +
                            instance_val[1] + '=' +
                            instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + unit[1] + '\n')
                    else:
                        netlist.writelines(
                            instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[
                                node[0]] + ' net' + node_pair[node[1]] + ' vb2 vdd ' + instance[0] + '_middle ' +
                            instance_val[
                                0] + '=' +
                            instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + unit[0] + ' ' +
                            instance_val[1] + '=' +
                            instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + unit[1] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[node[0]] + ' net' +
                    node_pair[node[1]] + ' ' + instance_val[-1] + '=' + instance_val[-1] + node_pair[
                        node[0]] + node_pair[node[1]] + unit[-1] + '\n')
                for i in range(len(instance_val) - 1):
                    tmp_conf.writelines(
                        'des_var ' + instance_val[i] + node_pair[node[0]] + node_pair[node[1]] + ' 2 ' + bound[
                            i] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[-1] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[
                        -1] + '\n')
            else:
                if idx <= 1:
                    netlist.writelines(
                        instance_head[0] + node_pair[node[0]] + node_pair[
                            additional_node[0]] + ' net_vinp net_vinn net' +
                        node_pair[additional_node[0]] + ' vb1 vdd ' + instance[0] + ' ' + instance_val[0] + '=' +
                        instance_val[0] +
                        node_pair[
                            node[0]] + node_pair[additional_node[0]] + unit[0] + ' ' + instance_val[1] + '=' +
                        instance_val[1] +
                        node_pair[
                            node[0]] + node_pair[additional_node[0]] + unit[1] + ' ' + instance_val[2] + '=' +
                        instance_val[2] +
                        node_pair[
                            node[0]] + node_pair[additional_node[0]] + unit[2] + '\n')
                else:
                    if x == 7 or x == 8:
                        netlist.writelines(
                            instance_head[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' net' + node_pair[
                                node[0]] + ' net' + node_pair[additional_node[0]] + ' vb1 vdd ' + instance[
                                0] + '_middle ' +
                            instance_val[
                                0] + '=' +
                            instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + unit[0] + ' ' +
                            instance_val[1] + '=' +
                            instance_val[1] + node_pair[node[0]] + node_pair[additional_node[0]] + unit[1] + '\n')
                    else:
                        netlist.writelines(
                            instance_head[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' net' + node_pair[
                                node[0]] + ' net' + node_pair[additional_node[0]] + ' vb2 vdd ' + instance[
                                0] + '_middle ' +
                            instance_val[
                                0] + '=' +
                            instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + unit[0] + ' ' +
                            instance_val[1] + '=' +
                            instance_val[1] + node_pair[node[0]] + node_pair[additional_node[0]] + unit[1] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' net' + node_pair[
                        additional_node[0]] + ' net' +
                    node_pair[node[1]] + ' ' + instance_val[-1] + '=' + instance_val[-1] + node_pair[
                        additional_node[0]] + node_pair[node[1]] + unit[-1] + '\n')
                for i in range(len(instance_val) - 1):
                    tmp_conf.writelines(
                        'des_var ' + instance_val[i] + node_pair[node[0]] + node_pair[additional_node[0]] + ' 2 ' +
                        bound[
                            i] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[-1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' 0.01 ' +
                    bound[
                        -1] + '\n')

        elif 17 <= x <= 24:
            if x % 2 != 0:
                if x == 17 or x == 19:
                    netlist.writelines(
                        instance_head[1] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[
                            node[0]] + ' net' + node_pair[node[1]] + ' vb1 vdd ' + instance[0] + '_middle ' +
                        instance_val[
                            1] + '=' +
                        instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + unit[1] + ' ' +
                        instance_val[2] + '=' +
                        instance_val[2] + node_pair[node[0]] + node_pair[node[1]] + unit[2] + '\n')
                else:
                    netlist.writelines(
                        instance_head[1] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[
                            node[0]] + ' net' + node_pair[node[1]] + ' vb2 vdd ' + instance[0] + '_middle ' +
                        instance_val[
                            1] + '=' +
                        instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + unit[1] + ' ' +
                        instance_val[2] + '=' +
                        instance_val[2] + node_pair[node[0]] + node_pair[node[1]] + unit[2] + '\n')
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' net' + node_pair[node[0]] + ' net' +
                    node_pair[node[1]] + ' ' + instance_val[0] + '=' + instance_val[0] + node_pair[
                        node[0]] + node_pair[node[1]] + unit[0] + '\n')
                for i in range(len(instance_val) - 1):
                    tmp_conf.writelines(
                        'des_var ' + instance_val[i + 1] + node_pair[node[0]] + node_pair[node[1]] + ' 2 ' + bound[
                            i + 1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[
                        0] + '\n')

            else:
                if x == 18 or x == 20:
                    netlist.writelines(
                        instance_head[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' net' + node_pair[
                            additional_node[0]] + ' net' + node_pair[node[1]] + ' vb1 vdd ' + instance[
                            0] + '_middle ' +
                        instance_val[
                            1] + '=' +
                        instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + unit[1] + ' ' +
                        instance_val[2] + '=' +
                        instance_val[2] + node_pair[additional_node[0]] + node_pair[node[1]] + unit[2] + '\n')
                else:
                    netlist.writelines(
                        instance_head[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' net' + node_pair[
                            additional_node[0]] + ' net' + node_pair[node[1]] + ' vb2 vdd ' + instance[
                            0] + '_middle ' +
                        instance_val[
                            1] + '=' +
                        instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + unit[1] + ' ' +
                        instance_val[2] + '=' +
                        instance_val[2] + node_pair[additional_node[0]] + node_pair[node[1]] + unit[2] + '\n')
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' net' + node_pair[
                        node[0]] + ' net' +
                    node_pair[additional_node[0]] + ' ' + instance_val[0] + '=' + instance_val[0] + node_pair[node[0]] +
                    node_pair[additional_node[0]] + unit[0] + '\n')
                for i in range(len(instance_val) - 1):
                    tmp_conf.writelines(
                        'des_var ' + instance_val[i + 1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' 2 ' +
                        bound[
                            i + 1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' 0.01 ' +
                    bound[
                        0] + '\n')

        else:
            print('error topo input !')

    netlist.close()
    tmp_conf.close()

def dac21_amp_generator(design_id, topo_vector):
    os.chdir('dac21_tmp_circuit')
    os.system('mkdir ' + design_id)
    os.chdir(design_id)
    os.system('mkdir circuit')
    os.chdir('circuit')
    os.system('mkdir netlist')
    os.chdir('../../..')

    netlistFooter = open('./dac21_tmp_circuit/' + design_id + '/circuit/netlist/netlistFooter', 'w')
    netlistFooter.writelines('// Footer end\n')
    netlistFooter.close()
    netlistHeader = open('./dac21_tmp_circuit/' + design_id + '/circuit/netlist/netlistHeader', 'w')
    netlistHeader.writelines('// Generated by amp topo opt program\n')
    netlistHeader.writelines('simulator lang=spectre\n')
    netlistHeader.writelines('global 0\n')
    netlistHeader.writelines('// Header end\n')
    netlistHeader.close()

    tmp_conf = open('./dac21_tmp_circuit/' + design_id + '/tmp.conf', 'w')
    netlist = open('./dac21_tmp_circuit/' + design_id + '/circuit/netlist/netlist', 'w')

    netlist.writelines('V0 (net_vin 0) vsource mag=1 type=sine\n')  # V_source setting

    netlist.writelines('G_vin_1 (net_1 0 net_vin 0) vccs gm=g_vin_1*1m\n')
    tmp_conf.writelines('des_var g_vin_1 0.01 1\n')
    netlist.writelines('R_1_0_prs (net_1 0) resistor r=rscl_vin_1_prs/g_vin_1*1K\n')
    tmp_conf.writelines('des_var rscl_vin_1_prs 40 80\n')
    netlist.writelines('C_1_0_prs (net_1 0) capacitor c=g_1_2/6.28*5p\n')

    netlist.writelines('G_1_2 (net_2 0 net_1 0) vccs gm=g_1_2*-1m\n')
    tmp_conf.writelines('des_var g_1_2 0.01 1\n')
    netlist.writelines('R_2_0_prs (net_2 0) resistor r=rscl_1_2_prs/g_1_2*1K\n')
    tmp_conf.writelines('des_var rscl_1_2_prs 40 80\n')
    netlist.writelines('C_2_0_prs (net_2 0) capacitor c=g_2_vo/6.28*5p\n')

    netlist.writelines('G_2_vo net_vo 0 net_2 0 vccs gm=g_2_vo*1m\n')
    tmp_conf.writelines('des_var g_2_vo 0.01 1\n')
    netlist.writelines('R_vo_0_prs (net_vo 0) resistor r=rscl_2_vo_prs/g_2_vo*1K\n')
    tmp_conf.writelines('des_var rscl_2_vo_prs 40 80\n')
    # netlist.writelines('C_vo_0_prs (net_vo 0) capacitor c=c_vo_0_prs*1p\n')
    # tmp_conf.writelines('des_var c_vo_0_prs 0.01 10\n')

    netlist.writelines('R_L net_vo 0 resistor r=0.15meg\n')  # RC load setting
    netlist.writelines('C_L net_vo 0 capacitor c=10n\n')

    node_pairs = [['_vin', '_2', '_vin_2'], ['_vin', '_vo', '_vin_vo'], ['_1', '_vo', '_1_vo'], ['_1', '_0', '_1_0'],
                  ['_2', '_0', '_2_0']]

    for idx, node in enumerate(node_pairs):
        x = topo_vector[idx, 0]
        node_pair = node_pairs[idx]
        instance_head, node, instance, instance_val, unit, bound, additional_node, additional_ins_head, additional_ins, additional_ins_val, additional_ins_unit, additional_ins_bound = get_node_info(
            x)
        if x == 0:
            pass
        elif 1 <= x <= 2:
            if idx <= 2:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[node[0]] + ' net' +
                    node_pair[node[1]] + ') ' + instance[0] + ' ' + instance_val[0] + '=' + instance_val[0] + node_pair[
                        node[0]] + node_pair[node[1]] + unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')
            else:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[node[0]] + ' 0) ' +
                    instance[0] + ' ' + instance_val[0] + '=' + instance_val[0] + node_pair[node[0]] + node_pair[
                        node[1]] + unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')
        elif x == 3:
            if idx <= 2:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[node[0]] + ' net' +
                    node_pair[node[1]] + ') ' + instance[0] + ' ' + instance_val[0] + '=' + instance_val[0] + node_pair[
                        node[0]] + node_pair[node[1]] + unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[node[0]] + ' net' +
                    node_pair[node[1]] + ') ' + instance[1] + ' ' + instance_val[1] + '=' + instance_val[1] + node_pair[
                        node[0]] + node_pair[node[1]] + unit[1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + ' 0.5 ' + bound[1] + '\n')
            else:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[node[0]] + ' 0) ' +
                    instance[0] + ' ' + instance_val[0] + '=' + instance_val[0] + node_pair[node[0]] + node_pair[
                        node[1]] + unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[node[0]] + ' 0) ' +
                    instance[1] + ' ' + instance_val[1] + '=' + instance_val[1] + node_pair[node[0]] + node_pair[
                        node[1]] + unit[1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + ' 0.5 ' + bound[1] + '\n')
        elif x == 4:
            if idx <= 2:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' (net' + node_pair[
                        node[0]] + ' net' + node_pair[additional_node[0]] + ') ' + instance[0] + ' ' + instance_val[
                        0] + '=' + instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + unit[
                        0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' 0.01 ' +
                    bound[0] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' (net' + node_pair[
                        additional_node[0]] + ' net' + node_pair[node[1]] + ') ' + instance[1] + ' ' + instance_val[
                        1] + '=' + instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + unit[
                        1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' 0.5 ' + bound[
                        1] + '\n')
            else:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' (net' + node_pair[
                        node[0]] + ' net' + node_pair[additional_node[0]] + ') ' + instance[0] + ' ' + instance_val[
                        0] + '=' + instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + unit[
                        0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' 0.01 ' +
                    bound[0] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' (net' + node_pair[
                        additional_node[0]] + ' 0) ' + instance[1] + ' ' + instance_val[1] + '=' + instance_val[1] +
                    node_pair[additional_node[0]] + node_pair[node[1]] + unit[1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' 0.5 ' + bound[
                        1] + '\n')
        elif x in [15, 16]:
            netlist.writelines(
                instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[node[0]] + ' 0 net' +
                node_pair[node[1]] + ' 0) ' + instance[0] + ' ' + instance_val[0] + '=' + instance_val[0] + node_pair[
                    node[0]] + node_pair[node[1]] + unit[0] + '\n')
            tmp_conf.writelines(
                'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')

            netlist.writelines(
                additional_ins_head[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                    additional_node[0]] + ' 0) ' + additional_ins[0] + ' ' + additional_ins_val[0] + '=' +
                additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + '/' + instance_val[0] +
                node_pair[node[0]] + node_pair[node[1]] + additional_ins_unit[0] + '\n')
            tmp_conf.writelines(
                'des_var ' + additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' 40 ' +
                additional_ins_bound[0] + '\n')
            netlist.writelines(
                additional_ins_head[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                    additional_node[0]] + ' 0) ' + additional_ins[1] + ' ' + additional_ins_val[1] + '=' +
                additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + additional_ins_unit[
                    1] + '\n')
            tmp_conf.writelines(
                'des_var ' + additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' 0.5 ' +
                additional_ins_bound[1] + '\n')
        elif x in [5, 6]:
            netlist.writelines(
                instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[node[0]] + ' 0 net' +
                node_pair[node[1]] + ' 0) ' + instance[0] + ' ' + instance_val[0] + '=' + instance_val[0] + node_pair[
                    node[0]] + node_pair[node[1]] + unit[0] + '\n')
            tmp_conf.writelines(
                'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')

            netlist.writelines(
                additional_ins_head[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                    additional_node[0]] + ' 0) ' + additional_ins[0] + ' ' + additional_ins_val[0] + '=' +
                additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + '/' + instance_val[0] +
                node_pair[node[0]] + node_pair[node[1]] + additional_ins_unit[0] + '\n')
            tmp_conf.writelines(
                'des_var ' + additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' 40 ' +
                additional_ins_bound[0] + '\n')
            netlist.writelines(
                additional_ins_head[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                    additional_node[0]] + ' 0) ' + additional_ins[1] + ' ' + additional_ins_val[1] + '=' +
                additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + additional_ins_unit[
                    1] + '\n')
            tmp_conf.writelines(
                'des_var ' + additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' 0.5 ' +
                additional_ins_bound[1] + '\n')
            # add input parasitic capacitor
            netlist.writelines(
                'C_input_' + str(int(idx)) + ' (net' + node_pair[node[1]] + ' 0) capacitor c=' + instance_val[0] +
                node_pair[node[0]] + node_pair[node[1]] + '/6.28*5p' + '\n')
        elif 7 <= x <= 14:
            if 11 <= x <= 14:
                netlist.writelines(instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[
                    node[0]] + ' 0 net' + node_pair[node[1]] + ' 0) ' + instance[0] + ' ' + instance_val[0] + '=' +
                                   instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[node[0]] + ' net' +
                    node_pair[node[1]] + ') ' + instance[1] + ' ' + instance_val[1] + '=' + instance_val[1] + node_pair[
                        node[0]] + node_pair[node[1]] + unit[1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[1] + '\n')

                netlist.writelines(
                    additional_ins_head[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                        additional_node[0]] + ' 0) ' + additional_ins[0] + ' ' + additional_ins_val[0] + '=' +
                    additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + '/' + instance_val[
                        0] + node_pair[node[0]] + node_pair[node[1]] + additional_ins_unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' 40 ' +
                    additional_ins_bound[0] + '\n')
                netlist.writelines(
                    additional_ins_head[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                        additional_node[0]] + ' 0) ' + additional_ins[1] + ' ' + additional_ins_val[1] + '=' +
                    additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + additional_ins_unit[
                        1] + '\n')
                tmp_conf.writelines('des_var ' + additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(
                    int(idx)) + ' 0.5 ' + additional_ins_bound[1] + '\n')
                # add input parasitic capacitor
                netlist.writelines(
                    'C_input_' + str(int(idx)) + ' (net' + node_pair[node[1]] + ' 0) capacitor c=' + instance_val[0] +
                    node_pair[node[0]] + node_pair[node[1]] + '/6.28*5p' + '\n')
            else:
                netlist.writelines(
                    instance_head[0] + node_pair[additional_node[0]] + node_pair[node[0]] + ' (net' + node_pair[
                        additional_node[0]] + ' 0 net' + node_pair[node[0]] + ' 0) ' + instance[0] + ' ' + instance_val[
                        0] + '=' + instance_val[0] + node_pair[additional_node[0]] + node_pair[node[0]] + unit[
                        0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[additional_node[0]] + node_pair[node[0]] + ' 0.01 ' +
                    bound[0] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' (net' + node_pair[
                        additional_node[0]] + ' net' + node_pair[node[1]] + ') ' + instance[1] + ' ' + instance_val[
                        1] + '=' + instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + unit[
                        1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' 0.01 ' +
                    bound[1] + '\n')

                netlist.writelines(
                    additional_ins_head[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                        additional_node[0]] + ' 0) ' + additional_ins[0] + ' ' + additional_ins_val[0] + '=' +
                    additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + '/' + instance_val[
                        0] + node_pair[additional_node[0]] + node_pair[node[0]] + additional_ins_unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' 40 ' +
                    additional_ins_bound[0] + '\n')
                netlist.writelines(
                    additional_ins_head[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                        additional_node[0]] + ' 0) ' + additional_ins[1] + ' ' + additional_ins_val[1] + '=' +
                    additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + additional_ins_unit[
                        1] + '\n')
                tmp_conf.writelines('des_var ' + additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(
                    int(idx)) + ' 0.5 ' + additional_ins_bound[1] + '\n')
                # add input parasitic capacitor
                netlist.writelines(
                    'C_input_' + str(int(idx)) + ' (net' + node_pair[node[0]] + ' 0) capacitor c=' + instance_val[0] +
                    node_pair[additional_node[0]] + node_pair[node[0]] + '/6.28*5p' + '\n')
        elif 17 <= x <= 24:
            if x % 2 != 0:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[node[0]] + ' net' +
                    node_pair[node[1]] + ') ' + instance[0] + ' ' + instance_val[0] + '=' + instance_val[0] + node_pair[
                        node[0]] + node_pair[node[1]] + unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[0] + '\n')
                netlist.writelines(instance_head[1] + node_pair[node[0]] + node_pair[node[1]] + ' (net' + node_pair[
                    node[0]] + ' 0 net' + node_pair[node[1]] + ' 0) ' + instance[1] + ' ' + instance_val[1] + '=' +
                                   instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + unit[1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[node[0]] + node_pair[node[1]] + ' 0.01 ' + bound[1] + '\n')

                netlist.writelines(
                    additional_ins_head[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                        additional_node[0]] + ' 0) ' + additional_ins[0] + ' ' + additional_ins_val[0] + '=' +
                    additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + '/' + instance_val[
                        1] + node_pair[node[0]] + node_pair[node[1]] + additional_ins_unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' 40 ' +
                    additional_ins_bound[0] + '\n')
                netlist.writelines(
                    additional_ins_head[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                        additional_node[0]] + ' 0) ' + additional_ins[1] + ' ' + additional_ins_val[1] + '=' +
                    additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + additional_ins_unit[
                        1] + '\n')
                tmp_conf.writelines('des_var ' + additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(
                    int(idx)) + ' 0.5 ' + additional_ins_bound[1] + '\n')
            else:
                netlist.writelines(
                    instance_head[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' (net' + node_pair[
                        node[0]] + ' net' + node_pair[additional_node[0]] + ') ' + instance[0] + ' ' + instance_val[
                        0] + '=' + instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + unit[
                        0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[0] + node_pair[node[0]] + node_pair[additional_node[0]] + ' 0.01 ' +
                    bound[0] + '\n')
                netlist.writelines(
                    instance_head[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' (net' + node_pair[
                        additional_node[0]] + ' 0 net' + node_pair[node[1]] + ' 0) ' + instance[1] + ' ' + instance_val[
                        1] + '=' + instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + unit[
                        1] + '\n')
                tmp_conf.writelines(
                    'des_var ' + instance_val[1] + node_pair[additional_node[0]] + node_pair[node[1]] + ' 0.01 ' +
                    bound[1] + '\n')

                netlist.writelines(
                    additional_ins_head[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                        additional_node[0]] + ' 0) ' + additional_ins[0] + ' ' + additional_ins_val[0] + '=' +
                    additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + '/' + instance_val[
                        1] + node_pair[additional_node[0]] + node_pair[node[1]] + additional_ins_unit[0] + '\n')
                tmp_conf.writelines(
                    'des_var ' + additional_ins_val[0] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' 40 ' +
                    additional_ins_bound[0] + '\n')
                netlist.writelines(
                    additional_ins_head[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + ' (net' + node_pair[
                        additional_node[0]] + ' 0) ' + additional_ins[1] + ' ' + additional_ins_val[1] + '=' +
                    additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(int(idx)) + additional_ins_unit[
                        1] + '\n')
                tmp_conf.writelines('des_var ' + additional_ins_val[1] + node_pair[additional_node[0]] + '_0' + str(
                    int(idx)) + ' 0.5 ' + additional_ins_bound[1] + '\n')
        else:
            print('error topo input !')

    netlist.writelines('.ends')
    netlist.close()
    tmp_conf.close()


from collections import OrderedDict
import torch
import torch.nn as nn
import sys

from tool.loss.smooth import smooth_focal_weight

import time
from torch.utils.data import DataLoader, Dataset
from torch.optim import SGD, Adam, Adadelta
from torch import save, load
import sklearn.metrics as metrics

from data_ import *
from backbone_ import *
from torch.nn import DataParallel
import numpy as np
import os
from loader1 import my_dataset as my_dataset_10s_smote
from tool.loss.focalloss import FocalLoss
from backbone_ import classifier

# device = torch.device("cuda:0")
all_data = []
s = "python3 {}".format(os.getcwd(), 'mit.py')
os.system(s)

class model():
    def __int__(self):
        pass

    def train(self):
        os.environ["CUDA_VISIBLE_DEVICES"] = '2'
        device_ids = [0]
        self.classifier = classifier()
        get_paprams(self.classifier)
        get_paprams(self.classifier.base)
        # data_set_eval = my_dataset(eval=True)
        # data_set = my_dataset_10s()
        # data_set_test = my_dataset_10s()
        data_set = my_dataset_10s_smote()
        data_set_test = my_dataset_10s_smote(test=True, all_data=data_set.all_data, all_label=data_set.all_label,
                                             index_=data_set.index)
        # data_set_eval = my_dataset_10s(eval=True)
        # data_set_combine = my_dataset(combine=True)
        batch = 300
        # totoal_epoch = 2000
        # print('batch:{}'.format(batch))
        # self.evaluation = evaluation
        data_loader = DataLoader(data_set, batch, shuffle=True, collate_fn=detection_collate)
        data_loader_test = DataLoader(data_set_test, batch, False, collate_fn=detection_collate)
        # data_loader_eval = DataLoader(data_set_eval, batch, False, collate_fn=detection_collate)
        self.classifier = self.classifier.cuda()
        self.classifier = DataParallel(self.classifier, device_ids=device_ids)
        optim = Adadelta(self.classifier.parameters(), 0.1, 0.9, weight_decay=1e-5)

        self.cretion = smooth_focal_weight()

        # data_loader_combine = DataLoader(data_set_combine, 225, False, collate_fn=detection_collate)
        self.classifier.apply(weights_init)
        start_time = time.time()
        count = 0
        epoch = -1
        while 1:
            epoch += 1
            runing_losss = [0] * 5
            for data in data_loader:
                loss = [0] * 5
                y = data[1].cuda()
                x = data[0].cuda()
                optim.zero_grad()

                weight = torch.Tensor([0.5, 2, 0.5, 2]).cuda()

                predict = self.classifier(x)

                for i in range(5):
                    loss[i] = self.cretion(predict[i], y, weight)
                tmp = sum(loss)

                tmp.backward()
                # loss5.backward()
                optim.step()
                for i in range(5):
                    runing_losss[i] += (tmp.item())

                count += 1
                # torch.cuda.empty_cache()
            end_time = time.time()
            print(
                "epoch:{a}: loss:{b} spend_time:{c} time:{d}".format(a=epoch, b=sum(runing_losss),
                                                                     c=int(end_time - start_time),
                                                                     d=time.asctime()))
            start_time = end_time

            save(self.classifier.module.base.state_dict(),
                 str(epoch) + 'base_c1.p')
            save(self.classifier.module.state_dict(),
                 str(epoch) + 'base_c1.p')

            self.classifier.eval()

            self.evaluation(self.classifier, data_loader_test, epoch)
            # self.evaluation(self.classifier, data_loader, epoch)

            self.classifier.train()
            if epoch % 10 == 0:
                adjust_learning_rate(optim, 0.9, epoch, totoal_epoch, 0.1)

    def evaluation(self, classifier, data_loader_test, epoch):
        # classifier.eval()
        all_predict = [[], [], [], [], []]
        all_ground = []
        with torch.no_grad():
            for data in data_loader_test:
                y = data[1].cuda()
                x = data[0].cuda()
                predict_list = classifier(x)
                for i in range(5):
                    predict, index = torch.max(predict_list[i], 1)
                    all_predict[i].extend(index.tolist())

                all_ground.extend(y.tolist())

        print("Accuracy:{}".format(metrics.accuracy_score(all_ground, all_predict[0])))
        print('precesion:{}'.format(metrics.precision_score(all_ground, all_predict[0], average=None)))
        print('recall:{}'.format(metrics.recall_score(all_ground, all_predict[0], average=None)))
        print('f-score:{}'.format(metrics.f1_score(all_ground, all_predict[0], average=None)))
        print("{}".format(metrics.confusion_matrix(all_ground, all_predict[0])))
        for i in range(5):
            tmp = metrics.accuracy_score(all_ground, all_predict[i])
            tmp2 = metrics.precision_score(all_ground, all_predict[i], average=None)
            tmp3 = metrics.recall_score(all_ground, all_predict[i], average=None)
            tmp4 = metrics.f1_score(all_ground, all_predict[i], average=None)
            print("Accuracy:{}".format(tmp))
            print('precesion:{}'.format(tmp2))
            print('recall:{}'.format(tmp3))
            print('f-score:{}'.format(tmp4))

    def test(self):
        self.classifier = classifier()
        self.classifier = self.classifier.cuda()
        data_set = my_dataset_10s_smote(test=True)
        data_loader_test = DataLoader(data_set, 300, False, collate_fn=detection_collate)
        all_predict = []
        all_ground = []
        self.classifier.eval()
        self.classifier.base.eval()
        total = 0
        with torch.no_grad():
            for data in data_loader_test:
                y = data[1].cuda()
                x = data[0].cuda()
                every_len = data[2]
                max_len = data[3]
                predict = self.classifier(x, every_len, max_len)[0]
                # predict = F.softmax(predict, 1)
                predict, index = torch.max(predict, 1)
                # total += predict.sum().item()
                ########
                ###
                all_predict.extend(list(index.cpu().numpy()))
                all_ground.extend(list(y.cpu().numpy()))
        # print(sum(all_predict))
        # print(sum(all_ground))
        print(metrics.precision_score(all_ground, all_predict, average=None))
        print(metrics.recall_score(all_ground, all_predict, average=None))
        print(metrics.f1_score(all_ground, all_predict, average=None))
        print(metrics.confusion_matrix(all_ground, all_predict))
        # pass

    # def evaluation(self, data_loader_test, epoch):
    #     para.smote = False
    #     self.classifier.eval()
    #     # self.front.eval()
    #     # this_classifier = classifier().cpu()
    #     # tmp = load(save_path+ str(epoch) + 'all_regular')
    #     # this_classifier.load_state_dict(tmp)
    #     # this_classifier.eval()
    #     all_predict = []
    #     all_ground = []
    #     with torch.no_grad():
    #         for data in data_loader_test:
    #             y = data[1].cuda()
    #             x = data[0].cuda()
    #             # x = self.front(x)
    #             every_len = data[2]
    #             predict, predict1, predict2, predict3, predict4 = self.classifier(x)
    #             predict = F.softmax(predict, 1)
    #             predict, index = torch.max(predict, 1)
    #             all_predict.extend(list(index.cpu().numpy()))
    #             all_ground.extend(list(y.cpu().numpy()))
    #     print('precesion:{}'.format(metrics.precision_score(all_ground, all_predict, average=None)))
    #     print('recall:{}'.format(metrics.recall_score(all_ground, all_predict, average=None)))
    #     print('f-score:{}'.format(metrics.f1_score(all_ground, all_predict, average=None)))
    #     self.classifier.train()
    # self.front.eval()

    # elif isinstance(m, nn.BatchNorm1d):
    #     m.weight.data.normal_(1.0, 0.02)
    #     m.bias.data.fill_(0)

if __name__ == '__main__':
    a = model()
    a.train()
    # a.test()
    # torch.set_default_tensor_type('torch.cuda.FloatTensor')
    # torch.set_default_tensor_type('torch.FloatTensor')


import tensorflow as tf
import tensorflow_datasets as tfds
import numpy as np
from sklearn.utils import shuffle
from hparams import HParams
import jax
from flax import jax_utils

try:
    from ..utils.normalizer import Normalizer
    from ..utils.utils import compute_latent_dimension
except (ImportError, ValueError):
    from utils.normalizer import Normalizer
    from utils.utils import compute_latent_dimension

hparams = HParams.get_hparams_by_name("efficient_vdvae")

def load_and_shard_tf_batch(xs, global_batch_size):
    local_device_count = jax.local_device_count()

    def _prepare(x):
        return x.reshape((local_device_count, global_batch_size // local_device_count) + x.shape[1:])

    return jax.tree_map(_prepare, xs)

def create_synthesis_cifar10_dataset():
    if hparams.synthesis.synthesis_mode == 'reconstruction':
        _, _, test_images = download_cifar10_datasets()

        test_data = tf.data.Dataset.from_tensor_slices(test_images)

        test_data = test_data.interleave(
            lambda x: data_prep(x, False),
            cycle_length=tf.data.AUTOTUNE,
            num_parallel_calls=tf.data.AUTOTUNE,
            deterministic=False)

        test_data = test_data.batch(
            hparams.synthesis.batch_size,
            drop_remainder=True
        )
        test_data = test_data.prefetch(tf.data.AUTOTUNE)

        test_data = tfds.as_numpy(test_data)
        test_data = map(lambda x: load_and_shard_tf_batch(x, hparams.synthesis.batch_size), test_data)
        test_data = jax_utils.prefetch_to_device(test_data, 10)
        return test_data

    elif hparams.synthesis.synthesis_mode == 'div_stats':
        train_data, _, _ = download_cifar10_datasets()

        n_train_samples = train_data.shape[0]

        train_data = tf.data.Dataset.from_tensor_slices(train_data)

        # Take a subset of the data
        train_data = train_data.shuffle(n_train_samples)
        train_data = train_data.take(int(hparams.synthesis.div_stats_subset_ratio * n_train_samples))

        # Preprocess subset and prefect to device
        train_data = train_data.interleave(
            lambda x: data_prep(x, False),
            cycle_length=tf.data.AUTOTUNE,
            num_parallel_calls=tf.data.AUTOTUNE,
            deterministic=False)

        train_data = train_data.batch(
            hparams.synthesis.batch_size,
            drop_remainder=True
        )
        train_data = train_data.prefetch(tf.data.AUTOTUNE)

        train_data = tfds.as_numpy(train_data)
        train_data = map(lambda x: load_and_shard_tf_batch(x, hparams.synthesis.batch_size), train_data)
        train_data = jax_utils.prefetch_to_device(train_data, 10)
        return train_data

    elif hparams.synthesis.synthesis_mode == 'encoding':
        train_data, _, _ = download_cifar10_datasets()
        train_filenames = make_toy_filenames(train_data)

        train_data = tf.data.Dataset.from_tensor_slices((train_data, train_filenames))

        train_data = train_data.interleave(
            named_data_prep,
            cycle_length=tf.data.AUTOTUNE,
            num_parallel_calls=tf.data.AUTOTUNE,
            deterministic=False
        )

        train_data = train_data.batch(
            hparams.synthesis.batch_size,
            drop_remainder=True
        )

        train_data = train_data.prefetch(tf.data.AUTOTUNE)

        train_data = tfds.as_numpy(train_data)
        train_data = map(lambda x: (load_and_shard_tf_batch(x[0], hparams.synthesis.batch_size), x[1]), train_data)
        return train_data

    else:
        return None

def named_data_prep(img, filename):
    inputs = data_prep(img, flip=False, return_targets=False)
    return tf.data.Dataset.from_tensor_slices(tensors=(inputs, filename[tf.newaxis]))

def data_prep(img, flip, return_targets=True):
    # Random flip
    if flip and hparams.data.random_horizontal_flip:
        img = tf.image.random_flip_left_right(img)

    # Normalize and possibly reduce bits
    normalizer = Normalizer()
    inputs = normalizer(img, reduce_bits=True)
    targets = normalizer(img, reduce_bits=True)

    if return_targets:
        # [1, H, W, C]
        return tf.data.Dataset.from_tensor_slices(tensors=(inputs[tf.newaxis, ...], targets[tf.newaxis, ...]))
    else:
        return inputs[tf.newaxis, ...]

def download_cifar10_datasets():
    # Ignore labels
    (x_train, _), (x_test, _) = tf.keras.datasets.cifar10.load_data()

    x_train = shuffle(x_train)
    x_test = shuffle(x_test, random_state=101)  # Fix this seed to not overlap val and test between train and inference runs

    x_val = x_test[:len(x_test) // 2]  # 5000
    x_test = x_test[len(x_test) // 2:]  # 5000
    return x_train.astype(np.uint8), x_val.astype(np.uint8), x_test.astype(np.uint8)

def make_toy_filenames(data):
    return [f'image_{i}' for i in range(data.shape[0])]

def create_cifar10_datasets():
    train_images, val_images, _ = download_cifar10_datasets()

    n_train_samples = train_images.shape[0]
    n_val_samples = val_images.shape[0]

    train_data = tf.data.Dataset.from_tensor_slices(train_images).cache()
    val_data = tf.data.Dataset.from_tensor_slices(val_images).cache()

    # Repeat data across epochs
    train_data = train_data.repeat()
    val_data = val_data.repeat()

    # Shuffle samples with a buffer of the size of the dataset
    train_data = train_data.shuffle(n_train_samples)
    val_data = val_data.shuffle(n_val_samples)

    train_data = train_data.interleave(
        lambda x: data_prep(x, True),
        cycle_length=tf.data.AUTOTUNE,
        num_parallel_calls=tf.data.AUTOTUNE,
        deterministic=False
    )

    val_data = val_data.interleave(
        lambda x: data_prep(x, False),
        cycle_length=tf.data.AUTOTUNE,
        num_parallel_calls=tf.data.AUTOTUNE,
        deterministic=False
    )

    # cache, Batch, prefetch
    train_data = train_data.batch(
        hparams.train.batch_size,
        drop_remainder=True
    )
    train_data = train_data.prefetch(tf.data.AUTOTUNE)

    val_data = val_data.batch(
        hparams.val.batch_size,
        drop_remainder=True
    )
    val_data = val_data.prefetch(tf.data.AUTOTUNE)

    train_data = tfds.as_numpy(train_data)
    val_data = tfds.as_numpy(val_data)

    train_data = map(lambda x: load_and_shard_tf_batch(x, hparams.train.batch_size), train_data)
    train_data = jax_utils.prefetch_to_device(train_data, 5)

    val_data = map(lambda x: load_and_shard_tf_batch(x, hparams.val.batch_size), val_data)
    val_data = jax_utils.prefetch_to_device(val_data, 1)
    return train_data, val_data


import torch
from torch import nn
import numpy as np
from tensorboardX import SummaryWriter
import argparse

from general_functions.dataloaders import get_loaders, get_test_loader
from general_functions.utils import get_logger, weights_init, create_directories_from_list
import fbnet_building_blocks.fbnet_builder as fbnet_builder
from architecture_functions.training_functions import TrainerArch
from architecture_functions.config_for_arch import CONFIG_ARCH

parser = argparse.ArgumentParser("architecture")

parser.add_argument('--architecture_name', type=str, default='', \
                    help='You can choose architecture from the fbnet_building_blocks/fbnet_modeldef.py')
args = parser.parse_args()

def main():
    manual_seed = 1
    np.random.seed(manual_seed)
    torch.manual_seed(manual_seed)
    torch.cuda.manual_seed_all(manual_seed)
    torch.backends.cudnn.benchmark = True

    create_directories_from_list([CONFIG_ARCH['logging']['path_to_tensorboard_logs']])

    logger = get_logger(CONFIG_ARCH['logging']['path_to_log_file'])
    writer = SummaryWriter(log_dir=CONFIG_ARCH['logging']['path_to_tensorboard_logs'])

    #### DataLoading
    train_loader = get_loaders(1.0, CONFIG_ARCH['dataloading']['batch_size'],
                               CONFIG_ARCH['dataloading']['path_to_save_data'],
                               logger)
    valid_loader = get_test_loader(CONFIG_ARCH['dataloading']['batch_size'],
                                   CONFIG_ARCH['dataloading']['path_to_save_data'])

    #### Model
    arch = args.architecture_name
    model = fbnet_builder.get_model(arch, cnt_classes=10).cuda()
    model = model.apply(weights_init)
    model = nn.DataParallel(model, [0])

    #### Loss and Optimizer
    optimizer = torch.optim.SGD(filter(lambda p: p.requires_grad, model.parameters()),
                                lr=CONFIG_ARCH['optimizer']['lr'],
                                momentum=CONFIG_ARCH['optimizer']['momentum'],
                                weight_decay=CONFIG_ARCH['optimizer']['weight_decay'])
    criterion = nn.CrossEntropyLoss().cuda()

    #### Scheduler
    if CONFIG_ARCH['train_settings']['scheduler'] == 'MultiStepLR':
        scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer,
                                                    milestones=CONFIG_ARCH['train_settings']['milestones'],
                                                    gamma=CONFIG_ARCH['train_settings']['lr_decay'])
    elif CONFIG_ARCH['train_settings']['scheduler'] == 'CosineAnnealingLR':
        scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer,
                                                               T_max=CONFIG_ARCH['train_settings']['cnt_epochs'],
                                                               eta_min=0.001, last_epoch=-1)
    else:
        logger.info("Please, specify scheduler in architecture_functions/config_for_arch")

    #### Training Loop
    trainer = TrainerArch(criterion, optimizer, scheduler, logger, writer)
    trainer.train_loop(train_loader, valid_loader, model)

if __name__ == "__main__":
    main()


"""
    Sk-Net Model for point clouds classification
"""

import os
import sys

BASE_DIR = os.path.dirname(__file__)
sys.path.append(BASE_DIR)
sys.path.append(os.path.join(BASE_DIR, '../utils'))
import tensorflow as tf
import numpy as np
import tf_util
import losses

from SkeypointNet_util import PDE_module,Aggregation,pointnet_fp_module
from keypointNet import reasoning_keypoints

def placeholder_inputs(batch_size, num_point,normal=True):
    if normal:
        pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 6))
    else:
        pointclouds_pl = tf.placeholder(tf.float32, shape=(batch_size, num_point, 3))
    labels_pl = tf.placeholder(tf.int32, shape=(batch_size,num_point))
    cls_labels_pl = tf.placeholder(tf.int32, shape=(batch_size))
    return pointclouds_pl, labels_pl,cls_labels_pl

def get_model(point_cloud, is_training,cls_label,NUM_CLASSES,NUM_CATEGORIES,bn_decay=None,normal = True,bn=True,
               num_keypoints = 128,k = 16,nsample = 64):
    """ Classification PointNet, input is BxNx3, output BxNUM_CLASSES """
    b = point_cloud.get_shape()[0].value
    n = point_cloud.get_shape()[1].value
    end_points = {}
    xyz = point_cloud[:,:,0:3]
    sn = None
    if normal:
        sn = point_cloud[:,:,3:6]
    end_points['xyz'] = xyz

    keypoints_xyz,res_feature,point_feature = reasoning_keypoints(point_cloud,num_keypoints,is_training)
    end_points['keypoints'] = keypoints_xyz

    knn_out,grouped_xyz,normalized_keypoints = PDE_module(keypoints_xyz,xyz,sn,mlp=[64, 128, 256],mlp2=[384,512],k=k,nsample=nsample,is_training=is_training ,bn_decay=bn_decay, scope='layer2')#BxMx3/512
    end_points['grouped_xyz'] = grouped_xyz

    aggregation_feature = Aggregation(knn_out, mlp=[768,1024], is_training=is_training, bn_decay=bn_decay, scope='layer3')#BxMx1024
    aggregation_pool = tf.reduce_max(aggregation_feature,axis=1)#Bx1024
    final_feature = tf.concat([aggregation_pool,res_feature],-1)

    net = part_segmentation(is_training,bn_decay,
             point_feature,
             aggregation_feature,final_feature,
             xyz,sn,normalized_keypoints,
             cls_label,
             seg_classes=NUM_CLASSES,
             NUM_CATEGORIES = NUM_CATEGORIES)

    return net, end_points

def part_segmentation(is_training,bn_decay,
         point_feature,
         aggregation_feature,final_feature,
         xyz,sn,normalized_keypoints,
         cls_label,
         seg_classes=50,
         NUM_CATEGORIES = 16):

    B = normalized_keypoints.get_shape()[0].value
    M = normalized_keypoints.get_shape()[1].value
    N = point_feature.get_shape()[1].value

    final_tiled = tf.tile(tf.expand_dims(final_feature,1),[1,M,1])
    final_ = tf.concat([final_tiled,aggregation_feature],-1)
    net = pointnet_fp_module(xyz, normalized_keypoints, tf.squeeze(point_feature), final_, [1024,512], is_training, bn_decay, scope='fa_layer1')

    net = tf_util.conv1d(net, 384, 1, padding='VALID',
                                    bn=True, is_training=is_training, scope='conv1d_2',
                                    bn_decay=bn_decay)

    cls_label_one_hot = tf.one_hot(cls_label, depth=NUM_CATEGORIES, on_value=1.0, off_value=0.0)
    cls_label_one_hot = tf.reshape(cls_label_one_hot, [B, 1, NUM_CATEGORIES])
    cls_label_one_hot = tf.tile(cls_label_one_hot, [1,N,1])
    if sn is not None:
        net = tf.concat([cls_label_one_hot,sn,net],-1)

    net = tf_util.conv1d(net, 256, 1, padding='VALID',
                                    bn=True, is_training=is_training, scope='conv1d_3',
                                    bn_decay=bn_decay)

    net = tf_util.conv1d(net, 128, 1, padding='VALID',
                                    bn=True, is_training=is_training, scope='conv1d_4',
                                    bn_decay=bn_decay)
    net = tf_util.dropout(net, keep_prob=0.6, is_training=is_training, scope='dp5')
    net = tf_util.conv1d(net, seg_classes, 1, padding='VALID',
                                    bn=False, is_training=is_training, scope='conv1d_5',
                                    bn_decay=None)

    return net

def get_loss(pred, label, end_points):
    """ pred: B*NUM_CLASSES,
        label: B, """
    # classification
    loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=pred, labels=label)
    classify_loss = tf.reduce_mean(loss)
    tf.summary.scalar('classify loss', classify_loss)
    # separate each other in keypoints
    keypoints = end_points['keypoints']
    separation_loss = losses.Separation_loss(keypoints,delta = 0.05)
    tf.summary.scalar('separation_loss', separation_loss)
    # close
    grouped_key = end_points['grouped_xyz']
    capture_loss = losses.Capture_loss(keypoints, grouped_key, theta = 0.05)
    tf.summary.scalar('capture_loss', capture_loss)

    total_loss = classify_loss + separation_loss + capture_loss

    tf.add_to_collection('losses', total_loss)
    return total_loss

if __name__ == '__main__':
    with tf.Graph().as_default():
        inputs = tf.zeros((32, 1024, 3))
        output, _ = get_model(inputs, tf.constant(True))
        #print(output)


import sys
import numpy
from pylab import *

x_threads = numpy.array([0, 1, 10, 20, 30, 40, 50, 100, 200, 400])

y_samples = numpy.array([0, 7046, 18951, 20599, 22349, 22663, 22407, 22369,
    22485, 20890])
y_average = numpy.array([0, 42, 160, 291, 402, 507, 643, 999, 1516,
    2840])
y_tps = numpy.array([0, 23.5, 62.4, 68.6, 74.3, 69.3, 69.4, 68.6, 75.2, 70.4])

if __name__ == '__main__':
    if sys.argv[1] == 'samples':
        plot(x_threads, y_samples, color='blue', label='samples(number of users)')
        # vlines(450, 0, 45000, color='red', linestyles='dashed', label='Error Line')
        legend(loc='upper left')
        savefig('./pic/samples.png')
        show()
    elif sys.argv[1] == 'average':
        plot(x_threads, y_average, color='blue', label='average')
        # vlines(450, 0, 4000, color='red', linestyles='dashed', label='Error Line')
        legend(loc='upper left')
        savefig('./pic/average.png')
        show()
    elif sys.argv[1] == 'tps':
        plot(x_threads, y_tps, color='blue', label='tps')
        # vlines(450, 0, 140, color='red', linestyles='dashed', label='Error Line')
        legend(loc='upper left')
        savefig('./pic/tps.png')
        show()
    else:
        print 'pass'


#-*- coding:utf-8 -*-
import os
from scipy.io import loadmat
from scipy.sparse import load_npz
from variables import POS_TAGS
from variables import CORPUS_PATH, RAW_IMG_PATH, DUPLICATES_CLUSTER_PATH
from variables import HIST_TXT_PATH, HIST_IMG_PATH
from variables import HIST_IMG_DICT_SIZE, HIST_IMG_LAYER_NUM

# ---------------------------------------------------------------------------------------
# Description   : Textual/Image Feature Hist Processor
# ---------------------------------------------------------------------------------------

def read_hist_txt(app):
	hist_txt = load_npz('/'.join([HIST_TXT_PATH, app + '.npz']))
	return hist_txt # [n_samples, n_features]

def read_hist_img(app):
	img_mat = loadmat('/'.join([HIST_IMG_PATH, app,
		'pyramids_all_' + str(HIST_IMG_DICT_SIZE) + '_' + str(HIST_IMG_LAYER_NUM) + '.mat']))
	hist_img = img_mat['pyramid_all'] # [n_samples, 4200]
	return hist_img

def get_hist_txt(app, hist_txt, report_id)->list:
	# get the text hist according to report_id
	reports = sorted(os.listdir('/'.join([CORPUS_PATH, app])))
	reports = [x.split('.')[0] for x in reports]
	return hist_txt[reports.index(report_id)].todense().tolist()[0]

def get_hist_img(app, hist_img, report_id):
	# get the image hist according to report_id, it may contain multiple images
	imgs = sorted(os.listdir('/'.join([RAW_IMG_PATH, app])))
	indices = [i for i,x in enumerate(imgs) if x.split('-')[0] == report_id]
	return [hist_img[i] for i in indices]

def get_hist_img_by_img_name(app, hist_img, img_name):
	imgs = sorted(os.listdir('/'.join([RAW_IMG_PATH, app]))) # may contain multiple images
	index = [i for i,x in enumerate(imgs) if x == img_name.encode('utf-8')]
	return [hist_img[i] for i in index][0]

def get_img_pos(img_name):
	index = 0
	for img in sorted(os.listdir('/'.join([RAW_IMG_PATH, app]))):
		if img_name == img:
			return index
		index = index + 1
	return -1

def preprocess_line(line):
	# print("POS_TAGS:")
	# print(POS_TAGS)
	# print("--------------------------------------------------")
	for tag in POS_TAGS:
		line = line.replace(tag, tag+' ') #pos_tag 后加一个空格??? 我觉得如果没有用到，去除pos tag或者更新库
	line = line.replace('  ', ' ').replace('__','-_').replace('\n','') #很奇怪啊？？？？
	return line

def parse_words(sentence):
	sentence = preprocess_line(sentence)
	words = [x.split('_')[0] for x in sentence.split(' ')] #去掉tag了
	return words

def processing(app, group_id, report_id): # read file content
	# print("group_id {} , report_id {}".format(group_id, report_id))
	f = open('/'.join([DUPLICATES_CLUSTER_PATH, app, group_id, report_id+'.txt']), 'r')
	line_list = [] # read one report into the list. A sentence is a list of words. A report is a list of sentence.
	for line in f.readlines():
		if line == '':
			break
		line = preprocess_line(line)
		words = [x.split('_')[0] for x in line.split(' ')]  # x.split('_')[0]是为了 app_NN -> app
		line_list.append(words) #就是只得到了原report中的单词（应该是这样）
	f.close()
	return line_list


import os
import time
import numpy as np
from multiprocessing import Process, cpu_count
from azint import AzimuthalIntegrator

def worker(ai, nrep):
    img = np.ones((2167, 2070), dtype=np.uint32)
    for i in range(nrep):
        ai.integrate(img)

def benchmark():
    start = time.perf_counter()
    base = os.path.dirname(__file__)
    poni = os.path.join(base, 'bench.poni')
    ai = AzimuthalIntegrator(poni,
                            (2167, 2070),
                            75.0e-6, 4,
                            2000,
                            solid_angle=True)
    end = time.perf_counter()
    print('Initialization time %.1fs' %(end - start))
    nworkers = cpu_count()
    nrep = 200
    procs = []
    for i in range(nworkers):
        p = Process(target=worker, args=(ai, nrep))
        procs.append(p)

    start = time.perf_counter()
    for i in range(nworkers):
        procs[i].start()

    for i in range(nworkers):
        procs[i].join()
    end = time.perf_counter()
    duration = end - start
    print('Eiger 4M: %.2f frames/s with %d worker processes' %(nworkers * nrep / duration, nworkers))


import argparse
import numpy as np
import os
os.environ["TOKENIZERS_PARALLELISM"] = "false"

from tqdm import tqdm
from sentence_transformers import SentenceTransformer, util

from utils import load_data

from contextualized_topic_models.models.ctm import ZeroShotTM
from contextualized_topic_models.utils.data_preparation import TopicModelDataPreparation
from contextualized_topic_models.utils.preprocessing import WhiteSpacePreprocessing
from contextualized_topic_models.evaluation.measures import CoherenceCV, InvertedRBO, TopicDiversity
from contextualized_topic_models.datasets.dataset import CTMDataset
import nltk

import pickle

parser = argparse.ArgumentParser()
parser.add_argument("--train", type=str, default="train.pkl", required=False)
parser.add_argument("--n_topics", type=int, default=20, required=False)
parser.add_argument("--model_type", type=str, default="LDA", choices=["LDA", "prodLDA"], required=False)
parser.add_argument("--tries", type=int, default=5, required=False)
parser.add_argument("--num_epochs", type=int, default=100, required=False)
parser.add_argument("--beta", type=float, default=1.0, required=False)
args = parser.parse_args()

nltk.download('stopwords')

texts, images = load_data(args.train)

sp = WhiteSpacePreprocessing(texts, stopwords_language='german')

preprocessed_documents, unpreprocessed_corpus, vocab = sp.preprocess()
tp = TopicModelDataPreparation("clip-ViT-B-32-multilingual-v1")

print("Text preprocessing")
training_dataset = tp.fit(text_for_contextual=unpreprocessed_corpus, text_for_bow=preprocessed_documents)

preprocessed_split = [t.split() for t in preprocessed_documents]

img_model = SentenceTransformer('clip-ViT-B-32')
print("Encoding images")
img_emb = img_model.encode(images, batch_size=128, convert_to_tensor=True, show_progress_bar=True)
img_emb = np.array(img_emb.cpu())
image_training_dataset = CTMDataset(X_contextual = img_emb, X_bow = training_dataset.X_bow, idx2token = training_dataset.idx2token)

for t in range(args.tries):
    model_dir = "models/text/%s_%s_%s_%s_%s/" %(args.model_type, args.n_topics, args.num_epochs, args.beta, t)
    os.makedirs(model_dir)
    log = open(os.path.join(model_dir,"log.txt"), "w")
    print("Train file: %s" %os.path.abspath(args.train), file=log)
    pickle.dump(training_dataset, open(os.path.join(model_dir, "training_dataset.pkl"), "wb"))
    pickle.dump(image_training_dataset, open(os.path.join(model_dir, "image_training_dataset.pkl"), "wb"))
    pickle.dump(tp, open(os.path.join(model_dir, "tp.pkl"), "wb"))
    pickle.dump(preprocessed_split, open(os.path.join(model_dir, "preprocessed_split.pkl"), "wb"))

    loss_weights = {"beta":args.beta}
    ctm = ZeroShotTM(bow_size=len(tp.vocab),
                     contextual_size=512,
                     n_components=args.n_topics,
                     model_type=args.model_type,
                     num_epochs = args.num_epochs,
                     loss_weights=loss_weights)
    ctm.fit(training_dataset, save_dir=model_dir, verbose=True)

    topics = ctm.get_topic_lists(25)
    irbo = InvertedRBO(topics=topics)
    td = TopicDiversity(topics=topics)
    cv = CoherenceCV(texts=preprocessed_split, topics=topics)

    print("IRBO: %2.4f" %irbo.score(), file=log)
    print("Diversity: %2.4f" %td.score(), file=log)
    print("Coherence: %2.4f" %cv.score(), file=log)
    log.close()