天线阵列遗传算法赋形优化Python实现

关于原理的介绍

本应用主要使用了两方面知识点,一方面是天线阵列合成公式;另一方面是遗传算法。通过遗传算法的数值优化,优化幅度/相位值,以达到优化方向图指标的作用。

 1. 天线阵列方向图合成

本公式被简化为了二维的合成,因为只要垂直面数据即可,适用于平面阵。
    
Am:幅度列表,Ph:x相位列表,f:为单元方向图组成的矩阵,H:阵列间距等位置信息

Ps:这个不理解的可以自己去相关书籍去查找,网上资料较少。

     
 2. 遗传算法
 

 

遗传算法的具体原理就不赘述了,具体的可以百度,网上很多相关资料,这个算法适合于多目标和多变量的优化求解。
本文这里主要涉及到的交叉知识点如下:

  • 基因:这里的基因就相当于是变量,我们需要的幅度/相位就是算法里面的基因了。不同的基因组成一个变量组,也就是一个染色体。也就是多个变量的一个组合就是染色体。
  • 交叉和变异:意思是给一个概率,相当于自然进化的一个选择,每两组染色体(变量值)进行较高概率的交叉,和较低概率的变异。这个概率值是可以调节的,以此来控制求解速度和范围。
  • 适应度:这个概念是最重要的一个函数,相当于AI里面的评价函数,每个染色体(一组解)会产生一个基因表达,也就是一个结果,将多个目标值融合进去进行评价,评分高的保留,不高的就剔除。可以一直循环,一直查看适应度评分,如果达到要求,即求解完成(当然也可以继续优化更高得分,不过一般较难)。

这个算法的效果主要需要调整的设置值是迭代次数,变异概率,交叉设置,适应度评价函数调整

 

Python代码开发

话不多说,上代码,主要分2部分,一部分是合成公式代码,另一部分是遗传函数的组合

预设变量

代码如下:                                                                                                                                        

# coding=utf-8
import numpy as np
import matplotlib.pyplot as plt
import csv

Generations = 100  # 遗传代数
POP_size = 5000  # 群体规模
CROSS_rate = 0.8  # 交叉概率
MUTATION_rate = 0.1  # 变异概率

f_pre = 16  # 目标第一上旁瓣
f_pre_weight = 0.5  # 所占权重
db_pre = 14.5  # 目标最大增益
db_pre_weight = 0.5  # 所占权重
xiaqing = 2  # 中心下倾角
xiaqing_min = 2
xiaqing_max = 12
xiaqing_range = np.arange(xiaqing_min, xiaqing_max + 1, 1, dtype=np.int32)  # 下倾角取值范围
Change = 1.5  # 下倾角精度
Ph_min = -180  # 相位取值范围
Ph_max = 180

Am = [0.6, 0.8, 1, 0.8, 0.6]  # 幅度
Am_sum = sum(Am)
for i in range(len(Am)):
    Am[i] = np.sqrt(Am[i] / Am_sum)
Freq = 1.71 * (10 ** 9)  # 频点
d = 0.121
Disl = [0, d, 2 * d, 3 * d, 4 * d]  # 间距列表

 如图所示,备注里面每个都写明了改参数的解释。这里测试的是一个5个阵子组成的一个方向图。

 

天线合成公式

具体就是把上面的公式改写成代码,并且尽可能用计算较快的方式。代码如下:

def CalEleMat(k_list, Freq, Disl, f):  # 这个函数是求解定值部分,不含幅度和相位,相当于求解公式中的V
    # 并且去掉了for循环,改用了效率更高的矩阵运算
    N = len(Disl)  # N是单元数,Disl是关于d的列表
    Disl = np.array(Disl)
    Disl = Disl.reshape(Disl.shape[0], 1)  # 矩阵行传列
    SpeedOfLight = 2.0943951023931954923084289221863e-08  # 2π/c的值,即换算k=SpeedOfLight*Freq
    AngleToRadian = 0.01745329251994329576923690768489  # π/180的值
    ThetaVec = np.array(k_list)  # 把角度列表变成一个一维数组
    ThetaSinVec = np.sin(ThetaVec * AngleToRadian)  # 1维的,sink值组成的数组
    CellPatAm = np.power(10, f / 20)  # db转成功率
    EleMat = CellPatAm * (np.exp(-1j * SpeedOfLight * ThetaSinVec * Disl * Freq))  # DisL是阵子间距的d列表,需要做行列变换,变成n行单列的数组
    return EleMat


def Cal(Am, Ph, EleMat):  # Am:幅度,Ph:相位,k_list:Theta角列表,Freq:频点,Disl:间距d列表,f:原始方向图矩阵
    Am = np.array(Am, dtype=np.float64)
    Ph = np.array(Ph, dtype=np.float64)
    AngleToRadian = 0.01745329251994329576923690768489  # π/180的值
    W = Am * (np.exp(-1j * Ph * AngleToRadian))
    PatData = np.dot(W, EleMat)
    PatData = 20 * (np.log10(abs(PatData)))
    return PatData

 这个公式经过验证,是可以执行的,合成的方向图与HFSS仿真结果是吻合的。

 

遗传算法代码

分为适应度函数,自然选择的2个函数,染色体交叉的函数,以及变异的函数,具体的代码都有注释。


def F(k_list, values):  # 分别求出最大增益和第一上旁瓣的数值
    db_max = max(values)
    k_list = list(k_list)
    values = list(values)
    x_max = k_list[values.index(db_max)]
    # print('最大值坐标:('+str(x_max)+','+ str(db_max)+')')  # 最大值的坐标

    x2 = k_list.index(x_max)
    x1_list = []
    for i in range(x2):
        if x_max - 31 < k_list[i] < x_max - 29:
            x1_list.append(i)
    x1 = min(x1_list)
    F = []
    for i in range(x1, x2):
        if values[i] - values[i + 1] > 0 and values[i] - values[i - 1] > 0:
            F.append(values[i])
        else:
            F.append(values[k_list.index(x_max - 30)])
    f_ = db_max - max(F)  # 第一上旁瓣
    return db_max, f_, x_max


def get_fitness(db_max, f_, db_pre, f_pre, db_weight, f_pre_weight, x_max, xiaqing):  # 根据增益和第一上旁瓣得出适应度函数值,单位一样,同样看待
    fitness_db = np.fabs(db_max - db_pre)
    fitness_f = np.fabs(f_ - f_pre)
    fitness = db_weight * (1 / fitness_db) + f_pre_weight * (1 / fitness_f)
    if np.fabs(x_max - xiaqing) >= Change or x_max < 0:  # 下倾角不满足条件的适应度值就为0
        return 0.0000001
    elif db_max > db_pre or f_ - f_pre > 0:
        return fitness ** 2 * 10000
    else:
        return fitness ** 2 * 1000


def select1(pop, fitness):  # 根据适应度函数值选择个体,越高的几率越高
    sum = np.sum(fitness)
    idx = np.random.choice(np.arange(POP_size), size=POP_size, replace=True, p=fitness / sum)
    return pop[idx]


def select2(pop):  # 保留一半的原始群体,再随机生成另一半,合并成新的群体
    pop_former = np.vsplit(pop, 2)[0]
    pop_later = np.random.uniform(Ph_min, Ph_max, size=(int(POP_size / 2), DNA_size))
    pop_new = np.vstack((pop_former, pop_later))
    return pop_new


def crossover(parent, pop_copy):  # 个体随机按概率在某个值上进行替换(两个个体之间进行)
    if np.random.rand() < CROSS_rate:
        i = np.random.randint(POP_size, size=1)
        cross_point = np.random.randint(DNA_size, size=1)
        # pop_copy=np.random.uniform(Ph_min, Ph_max, size=(POP_size, DNA_size))
        parent[cross_point] = pop_copy[i, cross_point]
    return parent


def mutation(child):  # 个体随机按概率在某个值上进行变异,变异的范围(Ph_min, Ph_max),保证个体的可变性
    for point in range(DNA_size):
        if np.random.rand() < MUTATION_rate:
            child[point] = np.random.uniform(Ph_min, Ph_max, size=1)
    return child

 

主程序

先是读取方向图数据的矩阵,然后进行迭代技术,把符合要求的记录下来


#读取单元方向图数据
def read_csv():
    datas = []
    for i in range(1, 6):
        name = 'h' + str(i) + '.csv'
        data = []
        with open(name) as csvfile:
            csv_reader = csv.reader(csvfile)
            header = next(csv_reader)
            for row in csv_reader:
                data.append(row)
        data = [[float(x) for x in row] for row in data]
        data = np.array(data, dtype=np.float64)
        k_list = data[:, 0]
        values = data[:, 1]
        datas.append(values)
    f = np.array(datas, dtype=np.float64)  # 获取单元方向图矩阵
    return k_list,f
if __name__ == '__main__':
    k_list, f=read_csv()
    N = len(Disl)
    DNA_size = len(AntennaArrayTable(N))
    pop = np.random.uniform(Ph_min, Ph_max, size=(POP_size, DNA_size))  # 就相当于相位个体,(-10,10相当于相位的取值范围)
    x_list = []
    y_list = []
    ph_list = []
    EleMat = CalEleMat(k_list, Freq, Disl, f)
    for _ in range(Generations):
        fitness = []
        for i in range(POP_size):
            Ph = pop[i]
            Ph = Trans_Phase(Ph, N)
            patdata = Cal(Am, Ph, EleMat)
            db_max, f_, x_max = F(k_list, patdata)
            fitness_eve = get_fitness(db_max, f_, db_pre, f_pre, db_pre_weight, f_pre_weight, x_max, xiaqing)
            fitness.append(fitness_eve)
            if db_max - db_pre > 0 and f_ - f_pre > 0 and np.fabs(x_max - xiaqing) < Change:
                ph_list.append(pop[i].tolist())
                print('一个合适的已经加入!!!')
        pop = select1(pop, fitness)
        pop = select2(pop)
        x_list.append(_)
        y_list.append(np.mean(fitness))
        pop_copy = pop.copy()
        for parent in pop:
            child = crossover(parent, pop_copy)
            child = mutation(child)
            parent[:] = child
        print('第%s代已经计算完成!!' % str(_ + 1))
    plt.plot(x_list, y_list)
    plt.title("迭代曲线",fontname="SimHei")
    plt.xlabel("遗传代数",fontname="SimHei")
    plt.ylabel("适应度值",fontname="SimHei")
    plt.grid()
    plt.show()


    def qu(list):  # 列表去重函数
        list1 = []
        for i in list:
            if i not in list1:
                list1.append(i)
        return list1


    ph_list = qu(ph_list)
    print('共有%d组值满足条件!' % len(ph_list))

    #随机取一个数值,看看效果如果
    rand_ph=ph_list[1]
    for i in range(len(ph_list)):
        Ph = Trans_Phase(ph_list[i], N)
        patdata = Cal(Am, Ph, EleMat)
        db_max, f_, x_max = F(k_list, patdata)
        if db_max>db_pre and f_>db_pre:
            print(db_max,f_)
            plt.plot(patdata)
    plt.grid()
    plt.show()

 至此,代码结束,我们看看运行的效果如何。

代码测试效果评估

条件1:增益>14.8,旁瓣>16,且中心下倾角在2附近。迭代100代。

 可以看到,遗传到50多代时,就出现了较好的值,一般来说,适应度值越高,效果也越好。统计出满足条件的相位值有1037组,大致的值和图形汇总如下:

 

 看吧,方向图还是很漂亮和一致的。

条件2:增益>14.83,旁瓣>17,且中心下倾角在2附近。迭代200代。

这时候的结果如下:

 

 

 这时候我们发现,满足的组数明显减少,适应度值也下降了。不过依旧获取了有效的解。(这组值在验证时候,100次迭代有时候是无解的)

条件2:增益>14.84,旁瓣>17,且中心下倾角在2附近。迭代200代。

此条件下,我们跑了多次,都无解,那就说明了,我们给定的条件下,几乎无法优化出最优解。

总结:

通过此程序,我们验证了遗传算法在阵列赋形中的可行性,在此基础上,通过方向图图形逆推幅度相位,或者是优化幅度,间距等都可以尝试一下,也可以导入S2P文件,更真实模拟数值,开发更好的方案预估工具。

  • 7
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
你好!对于进化算法天线阵列波束赋形中的应用,以下是一个简单的示例代码: ```python import numpy as np # 设置问题参数 num_antennas = 10 # 天线数量 num_beams = 4 # 波束数量 num_iterations = 100 # 迭代次数 # 初始化天线阵列权重 antenna_weights = np.random.randn(num_antennas, num_beams) # 定义目标函数 def fitness_function(weights): # 在这里根据具体问题定义评价函数 pass # 进化算法主循环 for i in range(num_iterations): # 计算适应度值 fitness_values = np.zeros(num_beams) for j in range(num_beams): fitness_values[j] = fitness_function(antenna_weights[:, j]) # 选择父代个体 parent_indices = np.argsort(fitness_values)[-2:] # 生成子代个体 offspring_weights = np.zeros((num_antennas, num_beams)) for j in range(num_beams): if j in parent_indices: offspring_weights[:, j] = antenna_weights[:, j] else: # 通过交叉和变异操作生成新个体 parent1 = antenna_weights[:, parent_indices[0]] parent2 = antenna_weights[:, parent_indices[1]] offspring_weights[:, j] = np.random.uniform(0, 1) * parent1 + (1 - np.random.uniform(0, 1)) * parent2 # 更新天线阵列权重 antenna_weights = offspring_weights # 输出最佳波束赋形方案 best_beam = np.argmax(fitness_values) print("最佳波束赋形方案:", antenna_weights[:, best_beam]) ``` 以上代码是一个简单的进化算法示例,用于优化天线阵列的波束赋形方案。你可以根据具体问题进行适当的修改和扩展。注意,这只是一个基本框架,实际应用中还需要根据具体的问题进行适当的调整和优化。希望对你有所帮助!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值