当前位置: 首页 > news >正文

DROO论文笔记

推荐文章DROO源码及论文学习

读论文《Deep Reinforcement Learning for Online Computation Offloading in Wireless Powered Mobile-Edge Computing Networks》的笔记

论文地址:用于无线移动边缘计算网络在线计算卸载的深度强化学习

论文代码地址:DROO源码

目录

一、Introduction

二、System Model 

三、Local Computing Mode

四、Problem Formulation 

五、THE DROO ALGORITHM 

Algorithm Overview

保序量化的代码 :

之前的方法:KNN

Offloading Policy Update

​Adaptive Setting of K

Convergence Performance

​Impact of Updating Intervals Δ

​Computation Rate Performance


一、Introduction

旨在解决无线供电的MEC网络中根据时变的无线信道条件优化地调整任务卸载无线资源分配,需要快速求解困难的组合优化问题,传统数值优化方法难以实现。

采用binary卸载策略,即无线设备(WD)的每个计算任务要么在本地执行,要么完全卸载到MEC服务器。提出基于深度强化学习的在线卸载(DROO),将原始优化问题分解为卸载决策子问题和资源分配子问题,设计保序量化卸载动作生成,消除传统数值优化方法的复杂性,通过动态自适应程序进一步降低计算复杂性。 

二、System Model 

三、Local Computing Mode

四、Problem Formulation 

 

五、THE DROO ALGORITHM 

整体框架代码: 

    N = 10                     #用户数量n = 30000                     # 时间帧数量K = N                   # 初始化 K = Ndecoder_mode = 'OP'    # 量化模式,可以是 'OP' (Order-preserving) 或 'KNN'Memory = 1024          # 内存结构的容量Delta = 32             # 自适应 K 的更新间隔print('#user = %d, #channel=%d, K=%d, decoder = %s, Memory = %d, Delta = %d'%(N,n,K,decoder_mode, Memory, Delta))# 数据加载和处理channel = sio.loadmat('./data/data_%d' %N)['input_h']#(30000, 10)->30000条N个信道增益rate = sio.loadmat('./data/data_%d' %N)['output_obj'] # 这个速率只用于绘图,不用于训练 DROO# 将信道值放大,以便更好地训练(这是深度学习中的常用技巧)channel = channel * 1000000# generate the train and test data sample index# 将数据分为 80:20# training data are randomly sampled with duplication if n > total data sizesplit_idx = int(.8 * len(channel))num_test = min(len(channel) - split_idx, n - int(.8 * n)) # training data size# 初始化DNNmem = MemoryDNN(net = [N, 120, 80, N],learning_rate = 0.01,training_interval=10,batch_size=128,memory_size=Memory)rate_his = []rate_his_ratio = []mode_his = []k_idx_his = []#索引K_his = []for i in range(n):if i % (n//10) == 0:print("%0.1f"%(i/n))#打印进度if i> 0 and i % Delta == 0:# index counts from 0if Delta > 1:#每 Delta 个时间步更新 Kmax_k = max(k_idx_his[-Delta:-1]) +1;#最近 Delta 个时间步内的最优K索引else:max_k = k_idx_his[-1] +1;K = min(max_k +1, N)#K 不超过 Nif i < n - num_test:#训练阶段# trainingi_idx = i % split_idx# 训练数据索引else:#测试阶段i_idx = i - n + num_test + split_idx# 测试数据索引h = channel[i_idx,:]#选择当前时间步的信道数据 h# the action selection must be either 'OP' or 'KNN'保序量化 K个卸载决策m_list = mem.decode(h, K, decoder_mode)
# 每个卸载决策的总传输速率 r_listr_list = []for m in m_list:r_list.append(bisection(h/1000000, m)[0])#将最大传输速率的卸载决策存储在经验回放中mem.encode(h, m_list[np.argmax(r_list)])# the main code for DROO training ends here# the following codes store some interested metrics for illustrations# memorize the largest rewardrate_his.append(np.max(r_list))#最大传输速率rate_his_ratio.append(rate_his[-1] / rate[i_idx][0])#最大传输速率与真实传输速率的比值# record the index of largest rewardk_idx_his.append(np.argmax(r_list))#最大传输速率的对应的在K个卸载决策中的索引(排名)# record K in case of adaptive KK_his.append(K)#本次的Kmode_his.append(m_list[np.argmax(r_list)])#记录最大传输速率的卸载决策

Algorithm Overview

Offloading Action Generation 

根据输入的无线信道增益 h 生成 k 个二元卸载决策 保序量化orKNN

def decode(self, h, k = 1, mode = 'OP'):h = torch.Tensor(h[np.newaxis, :])#(10,)->torch.Size([1, 10])self.model.eval()m_pred = self.model(h)#先用DNN输出一个连续卸载决策m_pred = m_pred.detach().numpy()# 再用这个连续决策生成 k 个二元卸载决策if mode is 'OP':#保序量化return self.knm(m_pred[0], k)elif mode is 'KNN':#KNNreturn self.knn(m_pred[0], k)else:print("The action selection must be 'OP' or 'KNN'")
保序量化的代码 :

输入m:DNN网络输出的N个relaxed卸载动作(0-1之间连续)

如:[0.99010485 0.62969816 0.4329 0.4087384  0.7058292  0.4560974 0.49688646 0.452399   0.20186329 0.21191679]

shape为N:(10,)

def knm(self, m, k = 1):# return k order-preserving binary actionsm_list = []# generate the first binary offloading decision with respect to equation (8)m_list.append(1*(m>0.5))#生成第一个二元卸载决策if k > 1:# generate the remaining K-1 binary offloading decisions with respect to equation (9)m_abs = abs(m-0.5)#首先计算 m 中每个元素与 0.5 的绝对差值idx_list = np.argsort(m_abs)[:k-1]#对绝对差值进行排序,并获取前 k-1 个最小差值的索引for i in range(k-1):if m[idx_list[i]] >0.5:# set the \hat{x}_{t,(k-1)} to 0m_list.append(1*(m - m[idx_list[i]] > 0))else:# set the \hat{x}_{t,(k-1)} to 1m_list.append(1*(m - m[idx_list[i]] >= 0))return m_list

输出m_list:K个保序量化后的动作

如:[array([1, 1, 0, 0, 1, 0, 0, 0, 0, 0]), array([1, 1, 0, 0, 1, 0, 1, 0, 0, 0]), array([1, 1, 0, 0, 1, 1, 1, 0, 0, 0]), array([1, 1, 0, 0, 1, 1, 1, 1, 0, 0]), array([1, 1, 1, 0, 1, 1, 1, 1, 0, 0]), array([1, 1, 1, 1, 1, 1, 1, 1, 0, 0]), array([1, 0, 0, 0, 1, 0, 0, 0, 0, 0]), array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]), array([1, 1, 1, 1, 1, 1, 1, 1, 0, 1]), array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])] 

之前的方法:KNN

最近邻二元动作 knn 计算输入向量 m 与所有可能的二元卸载决策之间的距离,找与输入向量最相似的 k 个二元决策

    def knn(self, m, k = 1):# list all 2^N binary offloading actionsif len(self.enumerate_actions) is 0:import itertools#笛卡尔积 所有可能的二元组合self.enumerate_actions = np.array(list(map(list, itertools.product([0, 1], repeat=self.net[0]))))# the 2-norm 计算与输入向量 m 的距离sqd = ((self.enumerate_actions - m)**2).sum(1)#输入向量 m 与所有可能决策向量的欧氏距离的平方idx = np.argsort(sqd)#距离最小的 k 个二元决策return self.enumerate_actions[idx[:k]]
Offloading Policy Update

经验回放:使用存储的数据样本训练DNN

Adam算法更新DNN的参数\theta_t

收集足够数量的新数据样本后,每\delta个时间步训练一次DNN

DNN迭代地从最佳状态动作对(𝐡𝑡,𝐱𝑡中学习,随着时间的推移生成更好的卸载决策输出

在有限内存空间约束的情况下,DNN仅从最新(且更精细)的卸载策略生成的最新数据样本中学习

Adaptive Setting of K

Convergence Performance

 Impact of Updating Intervals Δ
Computation Rate Performance

对于代码中optimization.py

方法是直接用的《Computation Rate Maximization for Wireless Powered Mobile-Edge Computing with Binary Computation Offloading》中提出的

包括先使用二分法找到最优的参数 v之后使用CD法优化模式选择,即固定其他通道的决策,仅改变当前通道的决策状态,对于每个通道,将其决策状态进行切换(0 变为 1,1 变为 0),计算相应的系统性能

论文地址具有二进制计算卸载的无线移动边缘计算的计算速率最大化,已标好代码中公式与论文中对应关系

# 二分搜索算法求解拉格朗日方程,先假定计算模式选择,然后优化传输时间分配
#线性搜索函数,需要两个输入,一个是信道矩阵,另一个是卸载动作,关于每个无线设备,除了W参数,其他的默认是同质的(我对代码的理解)。  
def bisection(h, M, weights=[]):# the bisection algorithm proposed by Suzhi BI# average time to find the optimal: 0.012535839796066284 s# parameters and equationso=100#是处理一位原始数据所需的周期数p=3#AP功率u=0.7#能量收集效率eta1=((u*p)**(1.0/3))/o#一个固定参数,不用理解ki=10**-26   #能量效率系数,跟计算机能耗相关的eta2=u*p/10**-10B=2*10**6#带宽Vu=1.1#Vu是原始数据(卸载数据)经过加密后的数据(原有数据在传输时进行额外添加)大小比原始数据的倍数epsilon=B/(Vu*np.log(2))x = [] # a =x[0], and tau_j = a[1:],时间分配矩阵M0=np.where(M==0)[0]#本地#为零或者1的索引M1=np.where(M==1)[0]#卸载hi=np.array([h[i] for i in M0])#本地、卸载设备对应的信道hj=np.array([h[i] for i in M1])#  h:信道信息数组,包含了每个通道的信道增益if len(weights) == 0:# default weights [1, 1.5, 1, 1.5, 1, 1.5, ...]weights = [1.5 if i%2==1 else 1 for i in range(len(M))]wi=np.array([weights[M0[i]] for i in range(len(M0))])wj=np.array([weights[M1[i]] for i in range(len(M1))])#w是每个WD的权重def sum_rate(x):#总传输速率 式11a x第一项是a,后面是每个设备的tausum1=sum(wi*eta1*(hi/ki)**(1.0/3)*x[0]**(1.0/3))sum2=0for i in range(len(M1)):sum2+=wj[i]*epsilon*x[i+1]*np.log(1+eta2*hj[i]**2*x[0]/x[i+1])return sum1+sum2def phi(v, j):#式17return 1/(-1-1/(lambertw(-1/(np.exp( 1 + v/wj[j]/epsilon))).real))def p1(v):#式18p1 = 0for j in range(len(M1)):p1 += hj[j]**2 * phi(v, j)return 1/(1 + p1 * eta2)def Q(v):#二分法 找到最优的参数 vsum1 = sum(wi*eta1*(hi/ki)**(1.0/3))*p1(v)**(-2/3)/3#local计算sum2 = 0for j in range(len(M1)):sum2 += wj[j]*hj[j]**2/(1 + 1/phi(v,j))#计算卸载return sum1 + sum2*epsilon*eta2 - v#这里来自公式19def tau(v, j):#式16return eta2*hj[j]**2*p1(v)*phi(v,j)# bisection starts here# 找到一个参数 v,使得函数 Q(v) 的值等于 0delta = 0.005 #二分法的精度UB = 999999999#初始的上界LB = 0#初始的下界while UB - LB > delta:v = (float(UB) + LB)/2if Q(v) > 0:LB = velse:UB = v
#  如果 Q(v) 的值大于 0,则将下界更新为当前的 v 值;否则,将上界更新为当前的 v 值x.append(p1(v))#p1(v)是a x第一项for j in range(len(M1)):x.append(tau(v, j))#计算每个WD的tau x后边是每个设备的taureturn sum_rate(x), x[0], x[1:]#总传输速率和时间分配向量 x 中的各个元素#然后使用坐标下降Coordinate DescentCD法来优化模式选择
def cd_method(h):N = len(h)#通道数量M0 = np.random.randint(2,size = N)#初始通道状态gain0,a,Tj= bisection(h,M0)#初始状态下的计算速率,a 和 Tjg_list = []M_list = []while True:# 固定其他通道的决策,仅改变当前通道的决策状态。# 对于每个通道,将其决策状态进行切换(0 变为 1,1 变为 0),计算相应的系统性能。for j in range(0,N):#对每一个通道 j 进行操作M = np.copy(M0)M[j] = (M[j]+1)%2#切换通道 j 的状态(0变为1,1变为0)gain,a,Tj= bisection(h,M)#调整后的计算速率、时间分配g_list.append(gain)M_list.append(M)g_max = max(g_list)if g_max > gain0:#寻找最优解gain0 = g_maxM0 = M_list[g_list.index(g_max)]#更新最卸载策略else:breakreturn gain0, M0

相关文章:

DROO论文笔记

推荐文章DROO源码及论文学习 读论文《Deep Reinforcement Learning for Online Computation Offloading in Wireless Powered Mobile-Edge Computing Networks》的笔记 论文地址&#xff1a;用于无线移动边缘计算网络在线计算卸载的深度强化学习 论文代码地址&#xff1a;DR…...

修BUG:程序包javax.servlet.http不存在

貌似昨晚上并没有成功在tomcat上面运行&#xff0c;而是直接运行了网页。 不知道为啥又报错这个。。。 解决方案&#xff1a; https://developer.baidu.com/article/details/2768022 就整了这一步就行了 而且我本地就有这个tomcat就是加进去了。 所以说啊&#xff0c;是不是&a…...

python常用库

目录 from sklearn import metrics:评估 ​编辑 svm&#xff1a; ​编辑 逻辑回归预测 ​编辑 朴素贝叶斯分类 ​编辑 主成分分析 ​编辑 其实就是求b.T的协方差阵 ​编辑 【因子分析&#xff0c;因子旋转有点复杂&#xff0c;略】 【层次聚类&#xff0c;原理…...

【UE5.3】笔记11

一、变量的SET&&GET 1、创建变量保存数据&#xff0c;如下图&#xff0c;找到左侧我的蓝图下的变量&#xff0c;新增一个&#xff0c;并选择类型。使用的时候直接将变量拖到蓝图中&#xff0c;此时会显示两个选项一个是获取一个是设置。 选择获取就是个GET蓝图&#x…...

加密与安全 密钥体系的三个核心目标之完整性解决方案

在密钥体系中&#xff0c;确保数据完整性是重要目标之一。以下为您详细讲解相关的完整性解决方案&#xff1a; 消息认证码&#xff08;MAC&#xff09;&#xff1a; 消息认证码是基于共享密钥和特定算法生成的固定长度代码。在发送方&#xff0c;将消息和共享密钥作为输入&…...

FastAPI 学习之路(四十一)定制返回Response

接口中返回xml格式内容 from fastapi import FastAPI, Responseapp FastAPI()# ① xml app.get("/legacy") def get_legacy_data():data """<?xml version"1.0"?><shampoo><Header>Apply shampoo here.</Header&…...

C++ //练习 15.9 在什么情况下表达式的静态类型可能与动态类型不同?请给出三个静态类型与动态类型不同的例子。

C Primer&#xff08;第5版&#xff09; 练习 15.9 练习 15.9 在什么情况下表达式的静态类型可能与动态类型不同&#xff1f;请给出三个静态类型与动态类型不同的例子。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 解释 当print_t…...

斐波那契查找算法

斐波那契查找原理&#xff0c;仅仅改变了中间结点(mid)的位置&#xff0c;mid不再是中间或插值得到,而是位于黄金分割点附近&#xff0c;即midlowF(k-1)-1(F代表斐波那契数列) F[k]F[k-1]F[k-2],>(F[k]-1) (F[k-1]-1)(F[k-2]-1)1 说明:只要顺序表的长度为F[k]-1,则可以将该…...

CAN总线学习

can主要用于汽车、航空等控制行业&#xff0c;是一种串行异步通信方式&#xff0c;因为其相较于其他通信方式抗干扰能力更强&#xff0c;更加稳定。原因在于CAN不像其他通信方式那样&#xff0c;以高电平代表1&#xff0c;以低电平代表0&#xff0c;而是通过电压差来表示逻辑10…...

zookeeper基础知识学习

官网&#xff1a;Apache ZooKeeper 下载地址&#xff1a;Index of /dist/zookeeper/zookeeper-3.5.7Index of /dist/zookeeperIndex of /dist/zookeeper/zookeeper-3.5.7 ZK配置参数说明&#xff1a; 1、tickTime2000&#xff1a;通讯心跳时间&#xff0c;zookeeper服务器与客…...

C语言内存管理深度解析面试题及参考答案(2万字长文)

在嵌入式面试时,C语言内存管理是必问面试题,也是难点,相关知识点可以参考: C语言内存管理深度解析​​​​​​​ 下面整理了各种类型的C语言内存管理的面试题: 目录 全局变量和局部变量在内存中分别存储在哪个区域? 静态变量和全局变量有什么区别? 什么是作用域?…...

C++基础(二)

目录 1.类和对象 1.1类的定义 1.2访问限定符 1.3类域 2.实例化 2.1实例化概念 2.2对象大小 3.this指针 4.类的默认成员函数 4.1构造函数 4.2析构函数 4.5运算符重载 1.类和对象 1.1类的定义 类的定义格式 class为定义类的关键字&#xff0c;Stack为类的名字&…...

R 绘图 - 中文支持

R 绘图 - 中文支持 R 是一种广泛使用的统计和数据分析编程语言&#xff0c;它提供了强大的绘图功能。然而&#xff0c;R 的默认设置并不直接支持中文&#xff0c;这可能会在使用 R 进行绘图时造成困扰&#xff0c;尤其是当需要在图表中添加中文标签或标题时。本文将介绍如何在…...

使用Godot4组件制作竖版太空射击游戏_2D卷轴飞机射击-标题菜单及游戏结束界面(九)

文章目录 开发思路标题菜单界面标题菜单脚本代码结束菜单界面结束菜单脚本代码 使用Godot4组件制作竖版太空射击游戏_2D卷轴飞机射击&#xff08;一&#xff09; 使用Godot4组件制作竖版太空射击游戏_2D卷轴飞机射击-激光组件&#xff08;二&#xff09; 使用Godot4组件制作竖版…...

[终端安全]-6 移动终端之应用程序安全

笔者在终端安全专题前面的文章中介绍了移动终端硬件安全和操作系统安全&#xff0c;本文主要介绍移动终端应用安全。在本文最前面&#xff0c;笔者想先解答一位朋友的疑问&#xff0c;为什么需要费心打造一个完整的面面俱到的安全体系&#xff1f; 1 移动终端安全的重要性 移…...

基于望获实时Linux的高性能运动控制器适配

在快速迭代的工业自动化与机器人控制领域&#xff0c;高性能运动控制器无疑是实现极致精度与效率的核心引擎。实时操作系统&#xff08;Real-Time Operating System,RTOS&#xff09;凭借其低延迟与高度确定性的特性&#xff0c;成为这些高精度、高速度应用的首选平台。 望获…...

电气工程VR虚拟仿真实训平台以趣味化方式增强吸引力

在工业4.0时代和教育信息化的双重推动下&#xff0c;我们致力于推动实训课件的跨界合作与共创。VR实训课件不仅促进了不同领域、不同行业之间的紧密合作&#xff0c;更让学习变得生动直观。我们凭借3D技术生动、直观、形象的特点&#xff0c;开发了大量配套3D教材&#xff0c;让…...

数据结构(单链表(1))

前言 线性表中有着许多的结构&#xff0c;如顺序表和链表。而单链表则是链表的最基础的一种形式&#xff0c;下面就让我们对其做一个了解。 概念 概念&#xff1a;链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次…...

STM32第十八课:SPIFlash

目录 需求一、SPI概要二、SPI配置1.开时钟2.配置IO3.配置&使能SPI 三、FLash操作函数1.SPI发送数据2.FLASH写使能3.FLASH等待操作完成4.FLASH页写操作5.FLASH读操作6.FLASH扇区擦除 四、需求实现 需求 通过SPI控制FLash进行数据的保存和删除。 一、SPI概要 在我们使用UA…...

如何使用IPython的并行计算能力处理大数据

目录 引言IPython概述 什么是IPythonIPython的特点 并行计算简介 什么是并行计算并行计算的优势 IPython的并行计算功能 IPython.parallel模块IPython并行架构 IPython的安装与配置 安装IPython配置并行环境 IPython并行计算的基础 任务分发与负载均衡核心概念&#xff1a;Cli…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...