重构故事

2024-10-02

重构故事(共6篇)

重构故事 篇1

安吉拉·卡特(1940-1992)是20世纪后半叶最具创造力,同时也是极富争议性的英国女作家。2008年英国《泰晤士报》举办关于“二战之后五十位最伟大的英国作家”的评选,安吉拉·卡特位居第十[1]。在短暂的一生中,卡特创作了九部长篇小说、五部短篇小说集,包括长篇小说《爱》、《霍夫曼博士的魔鬼欲望机器》、《新夏娃的激情》、《马戏团之夜》、《明智的孩子》等,短篇小说集《染血之室与其他故事》(以下简称《染血之室》故事集),短篇小说合集《焚舟纪》等。西方学术界对她的研究主要通过其作品的互文性、哥特风格、女性主义、后现代主义、魔幻现实主义等视角。而国内的卡特研究在广度和深度上未能超越国外的水平[1]。卡特以改写欧洲经典童话、解构父权神话的独创风格著称文坛。以短篇小说集《染血之室》为例:十个故事均源于欧洲经典神话故事集《格林童话》及17世纪法国作家夏尔·佩罗所著《夏尔·佩罗童话集》,而后三个故事《狼人》、《与狼为伴》、《狼女艾丽斯》均改编自这两个故事集中的名篇《小红帽》。在《染血之室》故事集中,卡特在经典童话中加入哥特元素,颠覆了传统童话中英雄救美的老套情节,重新定义了女性之美。卡特作品充分体现了解构主义反权威、反成规、反理性、反传统的特点,同时又兼具女权/女性主义批评对父权中心文化的颠覆性。因此可以说,卡特既是一个解构主义者,又是一个女性主义者。本文试图将这两种文学理论结合起来,分析卡特“狼人故事”《狼人》、《与狼为伴》中的女性形象重构,希望为卡特研究提供新的视角。

1 解构主义与女性主义的结合

解构主义是法国哲学家德里达倡导的一种反传统思潮。解构主义兴起于20世纪60年代,衰退于20世纪末。自这一理论确立以来,它的影响已经波及哲学、文学、艺术、神学等等几乎每一个文化领域。解构主义推翻了逻各斯中心主义,解构了重言语、轻文字的西方传统,将文字作为语言的本原和原型;解构了传统哲学/文学的二元对立,为了反对“一个本原,一个中心,一种绝对真理的”“在场的形而上学”,德里达发明了“异延”、“播撒”、“踪迹”表示意义在空间上的“异”和时间上的“延”、意义的漫散及转瞬即逝;解构主义还坚决反对理性是一个亘古如斯的超验结构[2]。

女权主义批评诞生于20世纪60年代末70年代初的欧美,至今仍在持续发展。它是西方女权主义运动高涨并深入到文化、文学领域的成果。它要求以一种女性的视角对文学作品进行全新的解读,对男性文学歪曲妇女形象进行猛烈的批判;它努力发掘不同于男性的女性文学传统,重评文学史;它探讨文学中的女性意识,研究女性特有的写作、表达方式,关注女作家的创作状况;它声讨男性中心主义传统文化对女性创作的压抑,提倡一种女权主义写作方式[2]。

由于女权主义批评与解构主义几乎出现于同一个时代,二者的相遇不可避免。同时,这两种批评方法在跨领域、反权威、反传统、反理性方面的共同特点,二者又互为补充、互为策略。

2《格林童话》及《夏尔·佩罗童话集》中的“小红帽原型”

《格林童话》是德国民间文学的瑰宝,被誉为“在欧美,凡是关心儿童文学的人,都认为这是一本必读的书”。这本儿童文学经典的背景是德国浪漫主义运动,担负起拯救、搜集德国民间文学的任务。然而,《格林童话》并非纯粹的德国民间童话,而是深受法国民间童话的影响。其中的名篇《小红帽》就明显源于法国作家夏尔·佩罗所著《夏尔·佩罗童话集》中的同名故事[3]。格林版的《小红帽》保持与佩罗版的《小红帽》大致相同的故事情节,都描述了一个天真可爱的小姑娘“小红帽”被大灰狼假扮的狼外婆欺骗的故事。但是为了发挥对儿童的教育功能,格林版《小红帽》删掉了佩罗版中儿童不宜的性暗示,并将结局作了迥然不同的改变:从德国童话《狼和七只小羊》里移植过来一个快乐的、惩恶扬善的结局,让小红帽被猎人从狼肚子中救了出来。与格林版相比,佩罗版《小红帽》保留了更多口述版民间故事的传统和精髓。而实际上,研究者发现:《小红帽》故事的源头乃是法国口传民间故事《外婆的故事》[3]。只不过,这个原始版的《小红帽》中,小女孩不叫“小红帽”,那顶深深烙印在人们脑海中鲜艳、可爱的小红帽是佩罗给戴上的。《外婆的故事》保留了口传故事中“小女孩吃外婆的肉、喝外婆的血”的恐怖情节,以及一些粗俗的性暗示,与佩罗故事中“小红帽”被大灰狼吃掉的结局不同,《外婆的故事》中小女孩最后用计逃脱。用原始版、佩罗版、格林版《小红帽》这三个版本比照卡特《狼人》和《与狼为伴》,会发现:卡特“狼人故事”是对经典格林版《小红帽》的颠覆,是原始版和佩罗版《小红帽》的升华;经典童话中可爱、乖巧、听话、纯洁的小天使在卡特笔下变为勇敢、冷静、机智、坦然享受肉体欲望的新女性。下文将分析卡特《狼人》、《与狼为伴》对“小红帽”形象的重构。

3 安吉拉·卡特“狼人故事”中的女性形象重构

卡特“狼人故事”通过改写情节、环境、人物、女孩与狼(狼人)的关系重塑了一个与“小红帽”完全不同的新女性形象。

3.1 情节、环境改写

在这两篇狼人故事中,女孩置身于天寒地冻、阴森恐怖、狼群出没的森林中,但她坚决要冒险去外婆家,最后靠自己的勇敢、智慧和魅力,一步步扭转了险境、化险为夷。这完全颠覆了童话故事“乖孩子要听妈妈话、否则会被大灰狼吃掉”的模式。

3.2 人物形象改写

作为父权文化产物的传统童话,《小红帽》刻画了理想的完美女性:漂亮、可爱、乖巧、听话、天真烂漫;但往往是非不分、容易被坏人欺骗。出于不同的目的,佩罗和格林开出了不同的方子。佩罗告诫年轻女孩:必须听妈妈的话,远离危险的男人,保持贞洁,否则下场很悲惨。格林则告诉孩子:世界还是美好的,女孩子只要漂亮、听话,就会得到帮助。而作为女性主义者的卡特,则完全颠覆了传统的天使形象,刻画出勇敢、沉着、敢于反抗、勇于自救的新女性形象。《与狼为伴》中的小女孩甚至推翻了女性的贞操道德观,为了保全生命主动配合狼人,最后她用勇气和智慧征服、改造了狼。

而狼的形象在卡特笔下也发生了改变。格林童话中的大灰狼虽然智商稍高,仍是一头野兽。佩罗笔下的大灰狼变成了危险的男人,利用时髦、迷人的外表勾引年轻女子,造成女孩家破人亡。而卡特给狼赋予了男人的人性,撕下狼凶狠贪婪的外衣、露出其虚弱的内心。

3.3 男女两性关系改写

传统童话中,强壮的男性始终占主导地位对女性进行无情迫害,作为弱势群体的女性只能忍气吞声、被动等待。运气好的女性能等到英雄相救,而运气差的女性无法逃脱羊入虎口的命运。而卡特扭转了传统的男女两性关系:勇敢的女性主动迎战,打败外强中干的男性;智慧的女性则征服和改造了凶狠的男性,重建了一个男女平衡的世界。

4 结束语

卡特终其一生,完成对传统的解构、对男性权威的颠覆。承载传统父权文化的经典童话,成为卡特解构男性逻各斯中心主义的靶子。对《小红帽》的女性形象解构,是卡特还击男权文化的一场漂亮的战役。而卡特其他故事的解构力量,正等待更进一步的发掘。

参考文献

[1]黄炜芝.安吉拉·卡特的重构童话文本研究[D].广州:暨南大学,2011.

[2]朱立元.当代西方文艺理论[M].上海:华东师范大学出版社,2005:341.

[3]彭懿.佩罗版《小红帽》与格林版《小红帽》的比较研究[J].中国儿童文化,2015(5).

[4]卡特,安吉拉.染血之室与其他故事[M].严韵,译.南京:南京大学出版社,2012:195-216.

重构故事 篇2

可重构数控系统是当前开放式数控技术的一个研究热点,与传统数控系统相比,可重构数控系统具有很多优点[1]。当前对数控可重构技术的研究主要集中在以下几个方面:①将现场可编程逻辑器件作为硬件系统的一个功能模块,研究如何对其实时编程以实现对硬件系统的重构设计[2,3];②利用组件技术设计数控系统,使数控软件系统具有一定的可重构性[4],或研究Windows系统的特点,基于Windows系统设计可重构的软件模型[5];③为了方便系统功能模块的增减,研究总线技术在可重构数控设计中的应用,利用通用串行总线设计系统模块间的通信[6]。上述研究的不足是:忽略了可重构数控系统的实现需要硬件、软件和模块间通信的协同设计。因此,本文将数控系统的重构分成相关联的3个层次:硬件系统重构、软件系统重构和模块级重构,并通过一个实际数控系统的设计,来阐述3个层次的应用及其相互关系。

1 数控系统软硬件开发平台的构建和可重构设计研究

1.1 可重构数控系统软硬件开发平台的建立

图1所示为数控系统的可重构硬件开发平台,以ARM、DSP和FPGA为硬件平台核心,系统采用主从式双CPU设计。ARM 处理器作为主芯片,具有通信管理、网络管理、人机交互、指令译码、故障诊断等功能。DSP 具有软件插补、位置控制、误差控制等功能。FPGA用于硬件插补器和外围接口电路的设计。由于FPGA能够通过编程改变其内部的硬件电路时序关系,所以数控系统的插补模块和外围接口电路能够根据整个系统的重构需要进行重新配置,使该硬件平台具有很强的重构能力。存储器主要用于整个系统运行的程序和数据的存储。各种硬件功能模块包括显示控制模块、键盘控制模块、数据采集模块、PLC控制模块等,主要用于实现各种具体应用功能。

笔者设计的可重构数控系统软件平台如图2所示,由如下几个部分组成。

(1)硬件服务模块。

该模块的主要功能为:①系统开始运行时,对硬件模块进行初始化;②系统运行过程中,其余软件模块只能通过硬件服务模块对硬件进行操作;③硬件模块进行重构时,用VHDL语言描述的文件通过该模块装载入FPGA模块。

(2)实时操作系统模块。

将自行开发的嵌入式实时操作系统TDNC-OS作为系统任务调度与开发平台,该模块的主要功能是处理由内外部事件引发的文件系统或功能任务的调度以及相应设备驱动的激活等。

(3)软件重构配置模块。

该模块的功能为:①原有系统参数的重新配置重构;②新功能的加入或新系统的重构生成。

(4)其余软件功能模块。

包括文件系统模块、各种插补功能模块、各种交互模块等,主要用于完成系统具体的工作功能[7]。

1.2 数控系统可重构设计研究

1.2.1 基于FPGA的硬件可重构模块设计

数控系统的可重构性要求数控系统能适时地调整自身的硬件结构以满足重构要求。现场可编程逻辑器件具有硬件电路在线可编程的特性,即它的硬件结构可以像软件程序一样被动态调整或修改[8]。图3为基于FPGA的可重构系统的结构框图,该系统可实现对数控系统从两轴联动到五轴联动的重构设计。由图3可知,可重构模块是ARM模块、DSP模块、交互模块和总线接口模块彼此间通信的桥梁。它不仅为信号传递提供可靠的通路,而且通过装载不同的配置文件,可重构出不同功能的数控系统。驱动模块和外部I/O接口模块(主要用于数控机床电气的控制)通过串行工业现场总线与数控系统相连,减小了模块之间连线的复杂度,提高了通信的可靠性,使整个系统模块的增减更加简便,极大缩短了数控系统模块级的重构时间。

基于常规SRAM编程,本系统基于FPGA的动态配置方案如图4所示。配置参数模块中的数据按照逻辑功能存放,用于配置FPGA内部的各逻辑模块。外部缓冲SRAM在ARM控制下,对系统重建时隙给予自适应的逻辑补偿,保证系统逻辑时序上的连续。系统整体功能采用FPGA硬件复用形式构筑,但系统功能的整合(系统重构、时隙补偿)由ARM规划和控制。

1.2.2 数控系统引导型软件重构开发平台的研究

数控系统的硬件重构和软件重构必须同步进行,才能实现整个系统的重构。根据该数控系统的结构特点,笔者设计了一种具有引导功能的系统重构开发平台,如图5所示。开发平台采用一种引导开发的模式,借助于预先定义的各种信息库,将使用特殊语言描述的用户功能要求转换成信息库中特定策略的组合,然后通过与ARM和DSP相匹配的代码编译器,将策略描述翻译后,再通过下载电缆传送至数控系统。

软件重构开发包括语言描述和引导设置两种开发方式。语言描述方式采用结构化的功能机制,预先定义出系统重构的算法结构,用户只需根据算法的提示加入自己功能要求的描述。图6所示为重构描述语言的结构,图中定义了一种新的插补算法来完成所需的复杂曲线拟合。开发平台提供独立的结构化描述语言,采用面向对象的编程思想,以功能对象群组的方式来描述数控组件对象的特定工作状态。语言描述方案可以通过灵活定义的算法规范深入系统内部的软件构成细节,适用于系统底层策略方案的自定义重构配置。引导设置采用开发向导的形式以图形化询问界面来定制用户的重构需求,一般用于较为简单的重构开发。图7所示为运动拟合精度的重新设定,较为简单,只需修改一些参数,因此,采用引导设置方式进行开发。

2 基于工业现场总线PROFIBUS-DP的模块可重构数控系统设计

数控系统的模块级重构要求重构过程简便快速,重构后的系统运行安全可靠,在物理空间上能够灵活分布[9]。PROFIBUS-DP是经过优化的高速廉价的通信总线,专用于自动化系统中分散的现场设备之间的通信。特别适合于分布式数字控制系统的高速数据传输。笔者基于前述的可重构软硬件数控平台,将12Mbit/s的PROFIBUS-DP作为数控系统模块间的通信总线,成功开发出了TDNCM4数控系统,图8为TDNCM4数控系统分布式模块结构图。在此基础上,下文将研究重构出新的更高性能的五轴联动数控系统TDNCH8的策略方法。

图9为将要设计的TDNCH8数控系统的分布式模块结构图,与图8相比最显著的变化就是增加了1个I/O控制器从节点和4个进给驱动从节点,变化的原因是TDNCH8数控系统需具有控制八轴五联动的能力。

表1列出了TDNCM4和TDNCH8数控系统在功能上的相同和不同之处,同时给出了从TDNCM4重构出TDNCH8系统时各种功能所采用的重构方式,“√”表示所在列的重构方式被采用。表1中所列数控功能的重构主要分为3类:

(1)不变。指TDNCM4和TDNCH8共有的功能。如平面直线插补、空间直线插补等功能,在数控系统重构升级的过程中,这部分功能可直接用到新的数控系统中。

(2)增加。指TDNCM4系统有此功能,但由于控制轴数的增加而必须对其进行扩展。如最大进给轴数、坐标系统等功能,需要从四轴增加到八轴。最大进给轴数的扩展是这样实现的:硬件重构增加轴控制通道数,软件重构解决新增轴的位置控制和配置问题,模块重构使新增的进给轴物理载体(一般是伺服电机驱动器和伺服电机)方便地连接到数控系统主控器上。显而易见,为实现控制轴数的重构升级,3种重构方式必须同时采用,缺一不可。坐标系统只需利用软件重构的方式,在前面提到的引导型软件重构平台上,在坐标系统函数库中增加新增四轴的坐标处理函数即可实现,硬件重构和模块重构的方式未用到。

(3)新增。指TDNCM4没有,而TDNCH8新增的功能。主要是一些更高级的插补功能,需要通过软件重构的方式来实现。

从上述分析中可以看出,基于TDNCM4系统重构出TDNCH8系统必须同时利用数控系统的硬件重构、软件重构和模块级重构技术,三者相辅相成,密不可分。换个角度分析,我们可以把数控系统的重构分为3个层次:①核心功能重构(一般指控制轴数和联动轴数的改变)需要同时采用3种重构方式才能实现;②工作功能(主要指插补功能)重构,只需通过软件重构就能实现;③辅助功能(包括坐标系统、程序管理系统、刀具管理系统等)重构,只需通过软件重构就能实现。只要判断出一个数控系统的重构升级属于哪个层次,就能决定其应该采用的重构方式,例如,如果只是想把刀具管理系统管理的刀具数从1024增加到2048,只需进行软件重构就可以。实际上,这种重构并未改变TDNCM4系统的根本性能,而是扩充或增强了其辅助功能。但如果把TDNCM4系统的控制轴数和联动轴数分别增加到8和5时的数控系统的重构属于核心功能的重构,需3种重构方式同时使用才能实现,而且重构后的系统在根本性能上与TDNCM4系统相比已经有了质的飞跃,新的更高性能的数控系统已经诞生。因此,如果一个可重构的数控系统平台具备上述3个层次的重构能力,那么必将能开发出从低端到高端的系列化数控产品。

在实际应用中,通过对TDNCM4数控系统的软硬件和组成模块的重构设计,成功开发出了五轴联动数控系统TDNCH8,并将其应用在TDNCM80A五轴加工中心上。显然TDNCM4和TDNCH8基于同一种设计结构,属同一个产品系列,只是性能高低不同。同理,采用相同的重构方法,也能方便地重构出车床控制系统、磨床控制系统等,从而形成一个数控系统产品系列。

3 结束语

论文提出从数控系统设计的硬件、软件和模块3个层次来研究可重构数控系统的设计,并给出了各个层次重构的实现方法。研究了3个层次在系统重构中协同应用的问题,并以一个实际设计为例,给出了不同数控功能重构的3种层次的选择方法。课题后续的工作将着重于进一步研究重构过程中的软硬件协同设计问题以及数控系统重构和机床重构的关系问题。

摘要:提出了一个软硬件可重构的数控系统平台方案,给出了硬件系统的重构策略,并设计了一个引导型软件重构开发平台。通过对数控系统的功能分析,将重构分为核心功能重构、工作功能重构和辅助功能重构,并以此研究了数控系统硬件重构、软件重构和模块重构的关系和协同设计问题。

关键词:数控系统,硬件重构,软件重构,模块重构

参考文献

[1]齐继阳,竺长安,王欢.基于USB和组件技术的可重构数控系统的研制[J].制造技术与机床,2007(12):17-20.

[2]Roque A O,Rene de J R,Gilberto H,et al.The Ap-plication of Reconfigurable Logic to High SpeedCNC Milling Machines Controllers[J].Control En-gineering Practices,2008,16(6):674-684.

[3]秦兴,王文,李为建,等.基于FPGA的硬件可重构数控系统的研制[J].仪器仪表学报,2002,23(3):407-409.

[4]齐继阳,竺长安.基于通用串行总线的可重构数控系统的研究[J].计算机集成制造系统—CIMS,2004,10(12):1567-1570.

[5]文立伟,王永章,路华,等.基于开放结构控制器的可重构数控系统[J].计算机集成制造系统—CIMS,2003,9(11):1018-1022.

[6]Wang Yuhan,Hu Jun,Li Ye.Study on a Reconfigu-rable Model of an Open CNC Kernel[J].Journal ofMaterials Processing Technology,2003,138(1/3):472-474.

[7]王太勇,王涛,杨洁,等.基于嵌入式技术的数控系统开发设计[J].天津大学学报,2006,39(12):1509-1515.

[8]徐跃,王太勇,赵艳菊,等.基于ARM和DSP的可重构数控系统[J].吉林大学学报(工学版),2008,38(4):848-851.

重构零售版图 篇3

今年会议的主题是“消费升级,跨界融合,重构零售新版图。”在昨天的领袖峰会上,大家对各个业态以及消费升级、跨界融合进行了深入讨论,在今天下午的大会上,峰会的各个小组还将就昨天讨论的成果和我们全体分享。

零售版图就是以消费为代表的市场份额。不同的行业、不同的企业、不同的业态,在不同的阶段你所占有的比例。在实体零售时代,零售资源中实体店铺是最最核心的资产。所以我们可以看到很多零售企业的总部,都挂着一幅地图上面插满了红旗,来说明企业在市场中的布局以及它的范围,这就是这个企业的版图。在实体企业时代,在零售企业快速发展的前十年,扩张、开店、跑马圈地是零售企业非常重要的策略。但是这几年我们可以看到市场网点在饱和,在很多城市,特别是一线城市已经出现了过剩,而且我们人均营业网点的面积,很多城市已经超过了发达国家。所以零售店铺效益在下降,甚至有的亏损难以为继。所以关店是市场的一种必然。一个是资源发生了变化,一个是市场的状况发生了变化,关店也就不足为奇了,我看到报纸上讨论关店问题的时候有很惊讶的感觉,其实关店是正常的现象,而且今后关店还会继续。在互联网时代,互联网的发展为没有线下实体优势的企业开辟了个新的空间,提供了新的发展机会。所以也有一些互联网企业横空出世,凭借在互联网上的巨大优势快速发展起来,使得零售格局和版图发生了变化。这时候流量就成了零售资源中很重要的一部分,前几年我们可以看到大家为争流量、买流量、控流量发生了激烈的新一轮的网上资源大战。

移动互联网的发展,为没有互联网资源,没有流量的企业提供了新的发展机会,也是新的企业包括线下实体零售企业一个新的发展机会,那就是通过这种方式我们与顾客有了更密切的接触,能够把原有资源通过移动互联网的方式和我们的会员发生更加密切的关系。在这一轮的争夺中,粉丝也好、会员也好,就成了新一轮的资源大战。其实我们也可以看到现在很多企业都在重新布局,布局什么?布局会员。很多企业都说到了他们未来发展会员的新思路,所以新一轮的会员大战也在一触即发。很多顾客成了同一类企业的会员,伴随着会员大战,企业跟会员凝聚力也发生了变化,我们看到很多企业留下了会员的手机,留下了会员的地址,但是没有留住会员的心。我的体会每次生日收到最多的是知道你生日的那些企业的没有温暖的问候。会员的管理是一个庞大的信息工程,我们的企业还都处于初级阶段,还有很长的路要走。抢夺资源、争夺流量、粉丝和会员,都是为了更好地吸引顾客、黏住客户,而未来,客户就成了零售企业最重要的资源。这不仅是指顾客的数量,更重要的是指顾客的质量,特别是与顾客的黏性,我们靠什么黏住顾客呢?现代的技术为我们提供了更好了解顾客需求,黏住顾客的技术手段。但是我想仅仅有这一点是不够的,因为很多的互联网企业他们有技术,但是并不一定把技术应用得很好。

想要获得消费者的支持,最重要的是零售商要和消费者建立起基于诚信基础上的信任消费关系,对于零售商来说,诚信是商业的基本道德,诚信是一种道德,也是你的基本能力,但是这也是我们目前商业社会中最最缺乏的。未来的零售版图在哪儿,不在天上、不在地上,不在线上,也不在线下,就在消费者的心中,你在消费者心目中有多大位置,你就有多大的市场。未来的版图在消费者心里,得民心者得天下。

稀疏重构算法 篇4

关键词:稀疏逼近,压缩感知,最优化,重构

图像恢复是通过计算机处理,对质量下降的图像加以重建或恢复的处理过程。因摄像机与物体相对运动、系统误差、畸变、噪声等因素的影响,使图像往往不是真实景物的完善映像[1,2,3]。在遥感图像处理中,为消除遥感图像的失真、畸变,恢复目标的反射波谱特性和正确的几何位置,通常需要对图像进行恢复处理,包括辐射校正、大气校正、条带噪声消除、几何校正等内容。在图像恢复中,对于一个目标函数求极小值,其中要求解的目标函数就是如下的一个不受约束的最优化问题[4,5,6,7]

minxϕ(x):f(x)+τc(x) (1)

其中,fRnR光滑函数,cRnR正则函数其中定义域xRn

对于式(1)具体到l2-l1中,有

minxRn12|y-Ax|22+τ|x|1(2)

其中,yRn,ARk×n,k<n,τR+标准欧几里得范数||2,||p代表lp范数,其中p≥1。式(2)可以用于求出欠定线性方程y=Ax的稀疏近似解[8,9]。

之前涉及上述快速算法包括文献[2]中的方法。在信号处理中关于l1惩罚项的记载参见文献[10]。对于上述最优化问题比较流行的新的应用,就是压缩感知(CS)[9]。最新结果显示,一个稀疏信号相对较少的数据投影,可以包含绝大多数信息。当设置了没有噪声的情况下,通过发现一个可以匹配原始信号的稀疏信号从而精确逼近。

1 方法概述

求解式(1),可以通过生成一些列的{xt,t=0,1,…}进行迭代求解,首先通过泰勒公式进行展开,并运用MM算法进行简化

xt+1argminz(z-xt)Τf(xΤ)+αt2|z-xt|22+τc(z)(3)

其中,αtR+。将式(3)进行化简得到

xt+1argminz|y-ut|22+ταtc(z)(4)

其中,utxt-1αtf(xt)。将式(3)中前两项,即(z-xt)Τf(xt)+αt2|z-xt|22可以看作一个二次可分离的逼近f(x),如果对于正则项c(z)是可分离的情况,则式(3)是可分离的形式。对于正则项c(z)是可分离的情况,可写为如下形式

c(x)=i=1nci(xi)(5)

式(2)中的l1正则项显然如式(5)所示,即ci(z)=|z|,当正则项是lpp范数时,c(z)=|z|pp=i|zi|p,也满足式(5),即正则项是可分离的。

对于正则项是块可分离的情况,如式(6)所示

c(x)=i=1nci(x[i])(6)

其中,x[1],x[2],…,x[m]是xm个不相交的子集。

综上所述,可以得到式(3)每一次迭代的解。当正则项c(x)是可分离的或者块分离的,可以得到有限的极小值。随后可以证明极小值的解收敛。

2 算法

2.1 算法框架

通过选取不同的正则项c(x),不同的方法选择αt,序号8中xt+1满足的条件不同,可以得到不同的实例化。

2.2 正则项c(x)是可分离的,对于子问题的求解

对于式(2)可以用MM算法求解,其中,f(x)=12|y-Ax|22。将其展开为f(x)=12y2-yΤAx+12xΤAΤAx。令,12y2=c,-yΤA=bΤ,12AΤA=Ρ+Ν,其中P是正的确定矩阵,N是负的确定矩阵。可得如下迭代公式

xt+1argminzzΤΡz+(b+2Νxt)Τz+(c-zΤΝz)+τc(z)(7)

2.3 对于αt的选取

可以用αtI来代替Hessian矩阵∇2f(x),令,st=xt-xt-1,Rt=∇f(xt)-∇f(xt-1),要求αtstRt从而得到αt

αt=argminα|αst-Rt|22=(st)ΤRt(st)Τst(8)

对于式(2)f(x)=12|y-Ax|22,则有αt=|Ast|22/|st|22。保证αt在算法结构中的αt∈[αmin,αmax]。

2.4 解的条件

对于每一次迭代,xt+1满足如下

ϕ(xt+1)maxi=max(t-Μ,0),,tϕ(xi)-σ2αt|xt+1-xt|2(9)

其中,σ∈(0,1)是一个常量,通常取一个接近于零的数。

2.5 终止条件

终止条件用于迭代程序的最后终止的条件。

2.6 对于的自适应选取

就像GPRS和IST算法,好的初始值对于问题的解是有益处的。关于自适应的选择就是首先给定一个初始的τ0,用于初始化算法,当第二次运行算法程序时,可以自适应地选择一个τ,这样可以减少算法的迭代次数。如果用一个稍大的τ来解决式(1),然后逐渐缩小到期望值,比直接给定一个较小的τ,通常会更有效。

对于τ,如果τ|AΤy|则关于式(2)的解是零向量。如果τ|AΤy|稍小,则认为过大,当τ|AΤy|时,则认为τ足够小。

3 实验结果

前提条件选取A是[20×40]的随机矩阵,分别选取x为不同的稀疏度,ζ=1.1。

4 结束语

介绍了用于解决大欠定最优化问题的稀疏重构算法SpaRSA,并改进了SpaRSA的解法以及对τ的选取,仿真结果表明,该算法能够更快的求出近似解,在正则项是凸的情况下,可以证明目标函数的极小解是收敛的。

参考文献

[1]STEPHEN J W,ROBERT D.Sparse reconstruction by sepa-rable approximation[J].IEEE Trance on Math,2009(1):981-986.

[2] CLAERBOUT J,MUIR F.Robust modelling of erratic data[J].Geophysics,1973(8):826-844.

[3] AXELSSON O.Iterative solution methods[M].Newyork:Cambridge University Press,1996.

[4]BARZILAI J,BORWEIN J.Two point step size gradient meth-ods[J].IMA Journal of Numerical Analysis,1988(8):141-148.

[5] OLSHAUSEN B A,FIELD D J.Emergence of simple-cell receptive field properties by learning a sparse code for natural images[J].Nature,1996,38(1):607-609.

[6]LEWICKI M S,SEJNOWSKI T J.Learning overcomplete rep-resentations[J].Neural Computer,2000,12(2):337-365.

[7] COMBETTES P,WAJS V.Signal recovery by proximal for-ward-backward splitting[J].SIAM Journal of Multiscale Model Simulation,2005(4):1168-1200.

[8] CLARKE F.Optimization and nonsmooth analysis[M].New York:Wiley Press,1983.

[9]CAND`ES E,ROMBERG J,TAO T.Stable signal recovery from incomplete and inaccurate information[J].Communica-tions on Pure and Applied Mathematics,2005,59(6):1207-1233.

面向数据重构算法 篇5

关键词:磁盘阵列,在线重构,面向数据重构算法

0 引 言

关于磁盘阵列在线重构的研究一直以来都是国内外研究热点。本文提出了面向数据重构算法,面向数据重构算法只对正被使用逻辑块上数据进行重构,而不需对整个磁盘进行数据重构。面向数据重构算法相对于现有重构方法显著改善了磁盘阵列的重构性能,并且没有降低重构过程中磁盘阵列服务性能。

1 面向数据重构算法

对于磁盘阵列在线重构,国内外相关研究主要从spare布局[1]、数据布局[2]和重构策略[3,4]三个方面来加速磁盘阵列在线重构。但是,现有重构方法都需要对整个磁盘进行数据重构,而不能根据磁盘实际使用情况进行重构。因此,面向数据重构算法的核心思想就是:当磁盘阵列出现磁盘失效时,仅重构正被使用逻辑块上数据,即可将磁盘阵列恢复至正常运行状态。面向数据重构算法的最大优点为:能够将失效磁盘上数据按需重构至空闲盘上,从而缩短了重构时间,提高了磁盘阵列的可靠性和可用性。.

基于面向数据重构算法的核心思想,我们构建了面向数据的RAID架构,对面向磁盘重构算法(DOR)进行了改进,实现了面向数据重构算法(DataOR)。

1.1 面向数据的RAID架构

通过对传统RAID进行简单改进,我们实现了面向数据的RAID架构(见图1所示)。面向数据的RAID架构与传统RAID架构根本差异就是:面向数据的RAID中未被使用逻辑块上数据一定为零;我们使用一个全局位图记录磁盘阵列中所有逻辑块(数据块和校验块)的使用情况,并通过在传统RAID转发读写请求路径上添加访问位图接口,从而实现了面向数据的RAID架构。面向数据RAID必须按照条带分配和释放逻辑单元,以避免引起附加的读写操作。

图1描叙了面向数据RAID架构的实现机制,磁盘阵列RAID5由4块磁盘构成,每块磁盘由两个逻辑块组成;磁盘阵列RAID5由8个逻辑块构成,包括6个数据块和2个校验块;位图vd-bmp上每个位对应一个磁盘逻辑块,位图vd-bmp上第0、4位对应磁盘disk0上逻辑块d00和d01,位图vd-bmp上第1、5位对应磁盘disk1上逻辑块d10和d11,其余对应关系类推。如图1(a1)和(a2)所示,对逻辑块d10进行读取操作时,首先访问位图vd-bmp的第1位,该位为0,因此,逻辑块d10上数据为零,直接返回零;如图1(b1)和(b2)所示,对逻辑块d00进行读取操作时,首先访问位图vd-bmp的第0位,该位为1,因此,逻辑块d00上已存放数据,读请求被直接转发给磁盘disk0;如图1(a1)和(a2)所示,对逻辑块d00进行写操作时,将新数据和新校验数据分别写入逻辑块d00和p30之后,将位图vd-bmp第0位和第3位设为1;如图1(c1)和(c2)所示,由于按照条带分配和释放逻辑单元,直接将位图vd-bmp第0、1、2和3位都设为0。

1.2 面向数据重构算法的原型实现

在面向数据的RAID架构上,通过对面向磁盘重构算法(DOR)改进,实现了面向数据重构算法(DataOR)。以下详细阐述DataOR算法的关键点:

(1) 面向数据RAID维护了正被使用逻辑块的位置标识(全局位图)。根据全局位图和磁盘阵列基本信息,可以创建磁盘阵列内任一磁盘上正被使用逻辑块的位置标识。

(2) 磁盘阵列发生磁盘失效时,创建失效磁盘上需要进行重构数据的位置标识(版本数据位图),以及初始状态为零的辅助位图。

(3) 通过版本数据位图和辅助位图相互协作,从而完成重构过程,使得磁盘阵列恢复到正常运行状态。

通过版本数据位图和辅助位图相互合作,重构管理构件实现了按需重构功能。版本数据位图为正被使用逻辑块的位置标识,辅助位图上所有位初始为0,两个位图上每一位与磁盘上4KB逻辑块一一对应。通过版本数据位图和辅助位图之间合作,可以判断逻辑块上数据是否有效。磁盘逻辑块上数据被定义了两种状态:

VALID—如果版本数据位图上某位为0或者辅助位图上某位为1,所对应逻辑块上数据则有效。

INVALID—如果版本数据位图上某位为1且辅助位图上相应位为0,所对应逻辑块上数据则无效,即逻辑块上数据必须重构。

在重构阶段,版本数据位图和辅助位图协作过程如下:

(1) 根据版本数据位图和辅助位图,顺序发出对于无效数据块的重构请求。当所计算出的数据被写入空闲盘之后,则将辅助位图上相应位设为1,从而标识逻辑块上数据已经有效。

(2) 用户读请求访问spare磁盘时,被访问逻辑块上数据有效,则直接访问spare磁盘;否则,通过同一条带上其它数据块构建出被访问的数据块,并写入spare磁盘,同时,将辅助位图上相应位设为1,从而标识被访问逻辑块上数据已经有效。

(3) 用户写请求访问spare磁盘时,将版本数据位图上相应位设为1,并直接将写请求发送给spare磁盘;写请求完成之后,则将辅助位图上相应位设为1,标识被访问逻辑块上数据已经有效。

2 性能分析

本节主要以面向磁盘重构算法作为参照,对面向数据重构算法进行性能分析。为了方便描述,面向磁盘重构算法简称为DOR,面向数据重构算法简称为DataOR。

本节的测试配置详细情况如下所述。服务器配置如下:Intel(R) Xeon(TM) CPU 2.40GHz,2GB内存,操作系统为32位的Fedora Core4,采用2.6.12-gentoo-r12内核,采用软RAID构成RAID5。RAID5基本属性如下设置:chunk大小为64KB,左对称算法,由9块磁盘构成,第3块磁盘失效。应用模式分别为:cello99(12-25、03-11、06-24、09-22和10-05)、F2.spc、F1.spc和tpcc94应用模式;对于cello99、F2.spc、F1.spc和tpcc94这四种应用模式,RAID5单块磁盘容量分别设为92GB、37GB、31GB和11GB。

图2描述了DataOR(RAID5)重构性能与DOR对比情况,相对于DOR,DataOR显著提高了重构性能。如图2所示,对于cello99应用模式,DataOR重构性能相对于DOR提高了1.7至2.2倍,对于F2.spc、F1.spc和tpcc94三种应用模式,DataOR重构性能相对于DOR提高了1倍左右。相对于DOR,DataOR重构性能得以显著提高的主要原因是重构数据量仅占磁盘实际分配空间的一部分。对于cello99应用模式,实际数据总量占磁盘实际分配空间的31%,对于F2.spc、F1.spc和tpcc94三种应用模式,实际数据总量占磁盘实际分配空间的47%至50%。

当实际存储容量远大于实际分配空间时,DataOR相对于DOR对重构性能有巨大改善。

3 结 语

本文介绍了面向数据重构算法的核心思想和实现机制。面向数据重构算法只对正被使用逻辑块上数据进行重构,而不需对整个磁盘进行数据重构。

测试结果说明了面向数据重构算法显著改善了磁盘阵列的重构性能和服务性能。磁盘阵列存储空间仅满足实际需求时,相对于DOR算法(目前最常用且最有效算法之一),面向数据重构算法将重构性能提高了1至2.2倍,并且没有降低重构过程中磁盘阵列服务性能。由于在更短时间将磁盘阵列恢复到正常运行状态,面向数据重构算法显著改善了磁盘阵列的服务性能。当磁盘阵列存储空间远大于实际分配空间时,面向数据重构算法对重构性能改善巨大。

参考文献

[1]Reddy A N N,Chandy J,Banerjee P.Design and Evaluation of Grace-fully Degradable Disk Arrays[J].Journal of Parallel and DistributedComputing,1993,17:28-40.

[2] Muntz R,Lui J.Performance Analysis of Disk Arrays Under Failure[C]//Proceedings of the 16th International Conference on Very Large Data Bases,1990,3:162-173.

[3]Fu Gang,Thomasian A,Han Chunqi,et al.Rebuild Strategies for Re-dundant Disk Arrays[C]//The Twelfth Conference on Mass StorageSystems and Technologies,2004,2:128-139.

重复代码的重构 篇6

1 什么是重构

1.1 重构的定义

最早倡导重构技术的是Ward Cunningham和KentBeck[3]。他们很早就把重构视作软件开发过程中的核心部分,并在自己的开发过程中运用重构实际解决问题。

而Ralph Johnson在UIUC(伊利诺伊大学厄巴纳尚佩恩分校)领导的小组最早对重构进行了理论研究。对于重构(refactoring),虽然研究者们给出了不同的定义,如Ralph Johson教授认为:重构是在为了提高效率与可维护性以及一些其它的原因的促使下,将一个面向对象的设计以不同方式进行重新组织,从而使设计更加灵活,重用性更强的过程。而另一专家,MartinFlower则给出了以下两种形式的定义。名词形式:对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本;动词形式:使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。

1.2 重构的意义

重构即在不改变代码功能的前提下,对代码的内部做出调整,进而优化程序的结构。通过重构,我们可以:(1)改进软件的设计,让逐渐模糊的设计变得清晰;(2)更清晰地展现代码的用途,使其易于理解;(3)深入地了解代码的行为,便于找到其中的bug;(4)增加对整个流程的认识,提高编程效率;(5)厘清程序结构,滤除臃肿代码,增强代码的可扩展性[4]。

2 重构时机

重构并不是软件开发过程中的某一阶段,而是存在于整个开发过程的。重构不是目的,而在于消除或降低代码的缺陷,保证代码的可阅读性和程序的可扩展性。

软件维护占软件生命周期的一半以上,所花费用更在60%以上[5]。因此,代码的可读性对代码的维护有着重大意义。没有章法、存在大量冗余、结构模糊的程序其可读性势必很差。如果我们不能轻易地读懂程序的功能,又何谈高效维护?所以当我们发现程序难以理解时,重构势在必行。

增强软件的可扩展性是重构的又一目标。当下软件的需求旺盛,对软件的功能需求也总会发生变更。很多时候开发者并不需要另起炉灶,从头开发新软件,而是在已有软件的基础上调整、添加新功能便可以了,二次开发正是这一背景下的产物。而提高复用性,减少软件开发的费用,增强软件的扩展性正是重构的所要解决的问题之一。因此,当软件的可复用性低,影响软件的可扩展性时,重构即为解决之道[6]。

以上是从长远角度考虑重构的时机。实际上,在开发的过程中,刚刚完成某项任务时,我们首先注意到的或许只是代码本身。审视我们的代码,我们常常会发现之前赶进度的驱使下编写出的代码有所欠缺,也就是Kent Beck和Martin Fowler所指的代码味道。

代码味道(code smells)是代码中的瑕疵,其发现在于设计及开发人员的经验直觉。当嗅到代码味道时,往往意味着我们需要用重构改善我们的程序。

在《重构 - 改善既有代码设计》一书中,Kent Beck和Martin Fowler列举了22种代码坏味道,常见的如重复代码、过长的函数、过大的类、过长的参数列表等等。这些代码坏味囊括了隐藏在程序中的隐患,预示着重构的必要性,是我们进行重构时不可或缺的指导方针。

3 重复代码的重构

3.1 重复代码的重构方法

顾名思义,重复代码就是代码中处于不同位置的相同或相似的代码。最简单的情况是重复代码位于同一个类中,此时只需采用Extract Method取出重复代码,接着在被提取处调用取出的方法即可。

稍微复杂些的情况是重复代码位于派生自同一父类的两个类中。对此需要对这两个类分别使用Extract Method,然后用Pull Up Method,将提取的代码放入超类中。而对于那些相似却不相同的代码,需先用Extract Method分开其差异部分和相似部分,从而得到一个独立函数。接着运用Form Template Method获得一个Template Method设计模式。如果发现不同函数以相似的算法实现同一功能,则可选用较为简单明了的一个,以Substitute Algorithm方法代替其它函数中的算法。

最为棘手的情况则是重复代码位于没有任何联系的两个类中。对此局面,应首先考虑含有重复代码的函数放在哪里更好。有些情况下,带有重复代码的函数只能属于其中一个类,另一个只应调用它。如果重复部分确实置于第三个类中更好,应首先对其中一个类采用Extract Class,使重复代码移至独立的类中,接着在两个类中分别引用该新类[7]。

3.2 从一个实例看重复代码的产生

以上是对重复代码重构的简要概述,下面结合一个具体实例剖析重复代码的产生,然后对该实例进行重构,最大限度地减少重复代码[8]。

在一个基于MFC的3D牙颌模型处理软件中,牙齿被分为萌出牙、义齿和恒牙。对于前二者,处理软件是需要做特别处理的。经测试后,两个与之相关的问题浮出水面。其一为当检测到模型中有义齿或萌出牙时,应不能进行下一步邻接面操作;其二是更改牙齿编号并刷新模型树后,义齿和萌出牙在模型中的标注信息不应丢失。

负责解决上述问题的程序员在阅读程序时,发现CTreeM odel View类中有下图所示代码,如图1所示,便将其作为解决问题的关键。不经意间,copy-paste风格所造成的恶果也就一步步显现了[9]。



首先,将图1中的代码拷贝至另一个类CTeethCut View中的点击邻接面按钮后的响应事件里。然后根据需要,进行修改,留下牙齿迭代器的遍历,并判断牙颌模型中是否存在义齿或萌出牙。若有,则以return退出;反之则进行下面的邻接面操作。具体如图2所示:

审视代码,发现Get Model()是一个未定义的方法,于是又在原处找到了其定义及具体实现,并将它也复制了过来,如图3所示。经过调试运行,确认第一个问题顺利解决。

对于第二个问题,在单步调试时,发现尽管牙齿的编号改变了,但是牙齿的Shell ID却不会改变。因此不妨在更新编号之前首先保存义齿和萌出牙的Shell ID,然后在调用更新牙齿编号函数之后,更新模型树之前重新依据牙齿的Shell ID设置牙齿的属性,这一过程再次使用了对牙齿迭代器的遍历,结果又是一段copy-paste风格代码,然后稍加修改,具体如图4所示:

至此,经过反复验证,两个问题得以解决。但是研究表明,copy-paste风格是重复代码产生的一大根源,大量存在的重复代码增加了编译和运行的额外开销,降低了程序的可理解性与可扩展性。而此时两处小小的修改,却都附带产生了重复代码,这在追求处理速度与效率的3D图形处理软件中显然不够完美[10]。为了解决这一问题,对重复代码进行重构势在必行。

3.3 重复代码的重构实例

我们分析这三处重复代码,发现第一段代码和后面两段与之重复的代码处于两个毫不相关的类中,而后面两段代码处于同一类中,且它们重复的部分都是因对第一段代码的复制而产生。进一步推敲这些重复代码,可以看出重复的关键在于对模型树的操作与判断,具体来说则是对模型树中的牙齿类型的判断与设置。考虑到第一段代码所在的类CTreeM odel View继承自CTree Ctrl类,处于三处问题的核心。因此简便起见,可对第一段代码采用Extract Method重构方法:将其中造成多次重复的代码段提取出来,作为一个独立的方法,然后在其提取之前的地方调用它,以保证程序外部行为在进行后面两处修改之前的一致性[11]。

提取方法后,我们依据代码段的功能给新方法取一个恰当的名字Iterator Teeth(),这也是重构所必需考虑的。对于新的方法,我们发现其内部用到的一些变量缺乏定义,所以我们先找到这些变量,然后将它们作为参数传入。同时应该注意,为避免造成过长参数列这一坏味,传入的参数应该控制在3个以内。具体情况如图5所示(只反映类中新增项)[12]。提取Iterator Teeth方法后,在原处调用这个方法,经过反复运行,发现外部行为没有改变。

接下来重新解决第一个问题:当检测到有义齿或萌出牙时,我们不进行邻接面操作。很明显,IteratorTeeth ( ) 方法中已有对义齿和萌出牙的判断,即IsE ruptibleT ooth( )和IsA rtificial Tooth( )。因此只需在CTreeM odel View类中添加一个bool型的公共成员变量m_bhave Eror Ar,并初始化为false。当对义齿或萌出牙的判断为true时,我们便将其置为true。然后在Teeth CutV iew类的On Tools Abuttingsurface函数中实例化CTreeM odel View对象 , 并判断其 成员变量m_bhave Eror Ar。若为true,说明存在义齿或萌出牙,则返回;若为false,则继续执行邻接面操作,类图如图6所示。通过几次操作,发现原有行为未发生改变,第一个问题顺利解决。

然后着手第二个问题的修改。其思路为首先给CTreeM odel View类添加两个公共的int型16位(一个牙颌的牙齿最多为16颗)数组成员变量m_shellidof Er[16]和m_shellidof Ar[16],在Iterator Teeth函数遍历牙齿模型时,若IsE ruptibleT ooth( )或IsA rtificial Tooth( )为true,则将该牙齿的Shell ID分别保存在与之相应的数组中。为了避免Iterator Teeth函数因执行几种不相关的任务而引入长方法坏味,且牙齿类型设置仍是对模型树的操作,于是在CTreeM odel View类中添加设置牙齿类型的公共函数SetS hellL ist Type( )。

首先还是遍历牙齿迭代器,然后在其内部遍历两个数组,如果发现数组m_shellof Er[16]保存的值与迭代器中牙齿的ShellI D相同,则将该Shell ID对应的牙齿模型设置为萌出牙;同理,若数组m_shellof Ar[16]中的值与迭代器中牙齿的Shell ID相同,就将该牙齿设置为义齿。最后,我们在CTeeth CutV iew类on Msg NumberDock View OK( )中的更改牙齿编号函数之后,更新模型树函数之前调用SetS hellL ist Type( )设置牙齿的类型,类图如图7所示,经过反复试验,原有的功能没有发生改变,至此,第二个问题也得以解决。

4 分析及结论

依据定义,重构是在不改变软件可观察行为的前提下,对其结构的优化。所以不改变程序的功能是其必要条件。为确保这一点,在进行重构的过程中,对程序的每做出一次细小的改动之后,都经过反复的测试,保证程序的外在行为没有发生变化[13]。当重构完成时,交由测试组进行综合测试,依然没有发现程序的外在行为有何改变。因此从这一点来看,重构是成功的。

最后是程序的优化。从外观上,相关代码重构之后的有效代码行数较之前有显著地减少:相关代码由重构前的52行减为重构之后的32行,降低38.5%。而程序的代码行数量能够直接反应程序的规模,间接体现了其复杂性。一般认为程序的代码越多会越复杂,也更容易出错。所以以较少的代码行实现相同的功能显然是一种改进[14]。与此同时,通过重构,上述3段代码不再重复,消除了冗余代码,避免了维护过程中对程序原始结构的破坏。

更为重要的是,将造成三段重复代码的关键———牙齿模型的遍历及其相关操作,单独提取作为一个方法,然后在需要使用的地方调用。这样不仅使代码看起来简洁明了,易于理解,而且有了这样一个方法后,若再出现涉及到它的新需求或功能变更时,便可以直接简单地调用它,避免再次重复,从而增强了程序的可扩展性。

重复代码作为首当其冲的代码坏味道,增加了编译运行的额外开销,降低程序的可理解性与可扩展性[15]。这里通过这个小的重构实例,揭示了重复代码产生的一大根源,展示了重复代码重构的具体过程,在一定程度上改善了代码的性能。

5 结束语

【重构故事】推荐阅读:

师生重构07-16

心室重构05-12

资源重构05-22

变迁—重构05-31

重构定位06-02

素质重构06-06

代码重构06-08

背景重构06-29

心肌重构07-25

重构思考07-27

上一篇:茄子热风干燥试验研究下一篇:非线性组合