没有合适的资源?快使用搜索试试~ 我知道了~
概率约束处理规则及其应用
115理论计算机科学电子笔记76(2002)网址:http://www.elsevier.nl/locate/entcs/volume76.html16页概率约束处理规则赫拉特Institutfur德国乌尔姆大学信息技术学院亚历山德拉·迪·皮耶罗意大利比萨大学信息学系赫伯特·维克利茨基英国伦敦帝国理工学院计算机系摘要经典的约束处理规则为约束求解器和约束程序的设计和实现提供了一个强有力的工具。递归的规则将约束(非确定性地)重写为更简单的约束,直到它们被解决。在本文中,我们介绍了一个扩展的约束处理规则(约束处理规则),即概率CHRs(PCHR)。这些允许规则的概率“加权”,指定其应用的概率。通过这种方式,我们能够形式化各种随机算法,例如模拟退火。该实现基于源到源转换(STS)。使用最近开发的STS原型,我们可以在不到一个小时的时间内用几行代码以简洁的方式1介绍约束处理规则(英语:Constraint Handling Rules,缩写为CLR)[7]是一种提交选择的并发约束逻辑编程语言,具有由重写原子公式的合取的保护规则组成的询问和告知。在这个意义上,它们超越了CCP框架[24,25],因为它们允许在规则的左侧(lhs)和传播规则上有多个原子。传统上,约束求解器用于指定和实现约束求解器和程序。规则重写约束(原子公式的合取)到更简单的,直到他们被解决。简化规则用更简单的约束代替约束。传播规则增加了新的约束,这可能会导致进一步的简化。随着时间的推移,已经发现,对于实现其他类别的算法,特别是在计算逻辑中,ESTA是有用的:在CC BY-NC-ND许可下开放访问。FRUhwirth,DiPierro,Wiklicky116约束定理证明结合演绎、溯因和约束组合前向和反向链接带完整性约束的自底向上评估自上而下的列表评价用可执行文法分析操纵属性化变量一般而言,产生式规则系统我们的概率扩展[9]是在概率并发约束编程(PCCP)框架[4]之后建模的。PCCP背后的动机是CCP框架内随机算法的形式化[24,25]。这些算法的特点是一个“硬币”装置(随机选择),它决定了信息的流动。在过去的十年中,随机算法在计算机科学的许多不同领域得到了广泛的应用,例如作为计算几何和数论的工具随机算法的好处是简单和快速。由于这个原因,许多问题的最著名的算法现在都是随机的[15],例如。组合优化中的模拟退火[1],遗传算法[11],特别是用于密码系统的概率素性测试[21],以及随机证明程序(例如线性逻辑[18])。在PCCP中,随机性以概率选择的形式表示,它取代了CCP和CCP的非确定性承诺选择,并允许程序在执行期间进行随机移动。对于概率规则选择(PCHR),这转化为概率规则选择。 在适用的规则中,通过考虑与每个规则相关联的相对概率来随机执行规则的承诺选择。例1.1下面的PCHR程序实现了抛硬币。 我们在程序示例中使用了具体的Prolog风格的语法。从语法上讲,概率(权重)是杂注注释的参数,在普通编译器中用于向编译器提供提示。在这里,它将启动源到源的转换。toss(Coin)<=> Coin=head pragma0.5.toss(Coin)<=>Coin=tail pragma 0.5.硬币的每一面都有相同的概率。 这种行为由两个规则建模,这两个规则具有相同的概率应用于查询投掷(Coin),要么导致Coin=head,要么导致Coin=tail。除了我们的基于约束的方法将概率整合到声明性设置中之外,还有关于概率逻辑程序、随机逻辑程序和贝叶斯逻辑程序的进一步丰富的文献,FRUhwirth,DiPierro,Wiklicky117[23][22][24][25][26][27]该文件的组织如下。在第二节中,我们简要讨论了经典的,非确定性的CHR的语法和语义。在第3节中,概率CHRs正式介绍,并通过一些例子进行了讨论。第4节中我们描述了一种基于源到源[10]第10话的转变最后,我们通过讨论几个可能的进一步发展和正在进行的工作来结束。2“”与“”的语义我们首先介绍了语法和语义的扩展之前,它的概率构造。我们假设对(并发)约束(逻辑)编程有一定的了解[16,8,19]。约束是一阶逻辑 我们区分内置(预定义)约束和用户定义的约束。内置约束是由预先定义的给定约束求解器处理的约束。约束条件是由约束程序定义的。2.1抽象语法在下文中,大写字母表示约束的连接定义2.1一个化简程序是一组CHR。有两种类型的CHR。一个化简程序的形式如下:H, Gj B以及形式为H)GjB的传播矩阵其中左手侧(lhs)H是双约束的合取的后面跟着符号j的保护G是内置约束的合取。一个形式为true j的平凡保护可能会被丢弃。 true是一个总是满足的内置约束。规则的右侧(rhs)由内置约束和约束B的连接组成。2.2操作语义通过一个状态转换系统给出了可编程逻辑程序的操作语义。语义使用交织来并行构造合取。通过推导步骤(转换、归约),可以从一个状态进行到下一个状态推导是推导步骤的序列定义2.2状态(或目标)是内在约束和外在约束的结合。初始状态(或查询)是任意状态。在最终状态(或答案)中,要么内置约束不一致,要么不再可能有新的FRUhwirth,DiPierro,Wiklicky118定义2.3设P是一个用于非线性约束的非线性规划,CT是一个用于内建约束的约束理论过渡关系!具体如下:简化好啊! (H = H0)^G ^B ^D如果P中的(H,GjB) 和CTj=8(D!9x(H=H0^G))传播好啊! (H = H0)^G ^B ^H0^D如果(H)G(jB)在P 和CTj=8(D!9x(H=H0^G))当我们使用程序中的规则时,我们将使用新符号重命名它的变量,这些变量形成序列x。 具有lhs H和保护G的规则适用于在约束D的上下文中的约束H0,当条件成立CTj=D!9x(H=H0 ^G).任何适用的规则都可以应用,但这是一个承诺的选择,不能撤销。如果一个单纯化规则(H,G |B)应用于非线性约束H0,则非线性过渡结果H0 从状态,将rhsB添加到状态,并且还添加等式H =H0和保护G。 如果传播规则(H)G|B)应用于H0 时,双极跃迁增加了B、H =H0和G,但不去除H0。 通过对相同的约束最多应用一次传播规则来避免平凡的非终止性[2]。现在我们更详细地讨论规则适用性条件 CT j= D!9x( H=H0^G).等式(H=H0)是一种符号速记法,用于使H和H 0中出现的约束条件的自变量相等。在操作上,规则适用性条件可以如下检查:给定D的内置约束,尝试求解内置约束(H = H0^G),而不进一步约束(接触)H0和D中的任何变量。 这意味着我们首先检查H0与H匹配,然后检查该匹配下的保护G。操作语义的具体化方式如下:状态分为两部分-一个用于内置约束,另一个用于操作约束。内置约束由内置约束求解器立即处理。将约束条件的结合实现为FIFO队列。当应用规则时,必须涉及最左边(rst)约束(匹配一个lhs原子)。我们将此约束称为当前活动约束。与剩余规则lhs原子匹配的其他约束可以从队列中的任何地方获取。如果应用规则,则可以根据规则类型移除活动约束,将规则的rhs的内置约束添加到状态中的内置约束,并且将来自规则的RHS的新的约束条件添加到队列。如果没有适用于当前活动约束的规则,则将其移动到队列末尾,下一个约束将变为活动约束。如果所有约束FRUhwirth,DiPierro,Wiklicky119~~如果队列中的队列已经传递,而没有应用新的规则,或者如果内置的约束变得不一致,则计算停止。最终结果(答案)是队列的内容以及内置约束。3可能性概率选择(Probabilistic Choice,PCHR)的特征在于概率性规则选择:在适用的规则中,通过考虑与每个规则相关联的相对概率来随机执行规则的承诺选择。3.1PCHR的语义和操作语义从语法上讲,PCHR规则与RISK规则相同,但增加了表示每个规则相对概率的权重:定义3.1概率简化公式为H,pGjB概率传播方程的形式为H)pGjB其中p是非负数。与每个替代规则相关联的概率表示通过足够频繁地重复相同的计算,计算将通过实际执行该规则选择而继续的可能性有多大这可以被看作是通过指定选择的频率来限制规则选择中的原始非确定性。概率规则选择构造的操作意义如下:给定当前约束,nd所有适用的规则。每个规则都与一个概率相关联。我们必须通过只考虑适用的规则来规范概率分布。这意味着我们必须重新定义概率分布,使这些概率之和为1。最后,根据归一化的概率分布选择一个适用的规则。因此,在转换系统的定义中,每个转换(由规则应用产生)将具有与其相关联的概率定义3.2过渡关系!p 对于PCHR,通过归一化概率yp-来索引,并且定义如下:简化好啊!(H=H0)^G^B^Dpi如果(H,p, Gj B)i nP和CTj=8(D!9x(H=H0^G))FRUhwirth,DiPierro,Wiklicky120pipi如果Prpj> 0p~i =Prjpjj1>:n否则其中,和rj,p,j是在当前状态下可应用于当前约束的所有规则rj的概率上的和,并且可应用规则的数量是n。该定义指定了与单个重写步骤相关联的概率。如果我们看整个重写序列,我们必须结合这些概率:推导的概率是与其每个推导步骤相关的概率的乘积。我们要用这个符号!以指示具有概率p的推导。最后,我们可能会在不同的推导过程中得到相同的结果,即不同的重写序列可能会得到相同的最终状态:在这种情况下,我们必须对与导致相同结果的每个推导过程相关联的概率进行例如,考虑以下PCHR计划:c(X)<=>1:X>=0|a(X)。c(X)<=>2:X=< 0|b(X).如果X大于零,查询约束c(X)将替换为a(X),如果X小于零,则替换为b(X)。在这两种情况下,只有一个规则适用,因此其标准化应用概率始终为1。 如果X是3 3分别 这意味着从长远来看,第二条规则将适用于是RST规则的两倍。3.2示例为了概述程序和算法的类型,我们可以很容易地使用PCHR指定,我们在下面的一些例子中提出。这些例子也将用于说明PCHR的许多有趣的特征,例如在[6]中引入的概率终止(参见例3.4和例3.5),以及将在3.3节中介绍的概率连续性。这里我们回顾一下概率终止的定义。定义3.3一个程序是概率终止的,如果一个不可能路径的概率为零。我们在示例中使用具体的Prolog风格语法。以下两个示例摘自PCCP[6],并已改编为PCHR。FRUhwirth,DiPierro,Wiklicky121例3.4[随机计数]考虑以下PCHR程序来计算自然数:nat(X)=>0.5:X=0。nat(X)=>0.5:X=s(Y),nat(Y)。在非概率实现中,可能使用适用规则中的固定规则顺序,并且然后查询nat(X)的结果总是X=0或者是由第二规则的夜间应用产生的夜间计算另一方面,概率性PCHR程序将计算所有自然数,每个自然数具有一定的可能性,该可能性随着数字变大而减小。例如,X=0的概率为0:5,X=s(0)的概率为0:25,等等。 更准确地说,生成n(0)的n个整数的概率是1=2n+1。请注意,尽管该程序不会终止于CHR,但它在概率上终止于PCHR,因为在夜间长度为零。例3.5[Gambler's Ruin]考虑下面的PCHR程序,它实现了一个所谓的一维随机游走,”说明了什么也被称为\Gambler's Ruin”[12]:walk ( X , Y ) <=>1 : X\=Y |walk( X+1 , Y ) . walk ( X , Y )<=>1 : X\=Y |walk( X , Y+1 ) .walk(X,Y)<=>1:X=Y|真的设X为赢的游戏数(或赢的英镑数),Y为输的游戏数(或输的英镑数)。然后我们可以将walk(1,0)解释为游戏从一英镑的赌注开始,当所有的钱都输完时结束。概率论的基本结果表明,游戏将以概率为1的破产赌徒结束,尽管事实上存在着(很少)无限衍生的可能性,即非常富有的赌徒。虽然有这些在nite计算(对应于在nite随机游走),与所有nite推导(即,[12][13][14][15][16][17][18][19][19] 因此,(所有)无限导子的因此,这个程序,经典上不会终止,但在概率意义上确实会终止:如果一个人继续玩,几乎可以肯定他最终会失去一切。在下面的例子中,我们使用概率零来表示绝对规则偏好和对保护的否定(if-then-else)。例3.6下面的PCHR程序是merge/3的一个实现,即当输入列表的元素到达时,将两个列表合并为一个列表因此,nal列表中的元素的顺序可以从计算到计算而不同。FRUhwirth,DiPierro,Wiklicky122merge([],L2,L3) <=>1: L2 = L3。merge(L1,[],L3) <=>1: L1 = L3。合并([X| L1,L2,L3)<=>0:L3= [X| L],合并(L1,L2,L)。合并(L1,[Y| L2]、L3)<=>0:L3= [Y| L],合并(L1,L2,L)。与规则相关联的概率的效果如下:如果查询中涉及空输入列表,则总是选择前两个规则中的一个,即使递归的两个规则中的一个也可以应用。查询merge([a],[b],L3)可以导致L3=[a,b]或L3=[b,a]。由于在这种情况下,前两个规则不适用,并且两个递归规则作为结果具有相同的概率,因此两个结果的可能性相等从这个意义上说,PCHR实施合并是有效和公平的。下一个例子展示了参数化概率的使用模拟退火(SA)是最通用和最流行的随机优化算法之一。它的灵感来自于热力学中退火的物理过程[20]:如果对液体进行缓慢冷却,它会自然冻结到能量最小的状态。SA算法将退火应用于成本函数的最小化,以解决组合优化领域中的问题。SA算法试图通过迭代地向更好的解决方案前进,同时避免陷入局部最优,从而找到全局最优解。该算法通过从一个解到另一个解的随机行走进行,即从当前解随机计算新的解。每个解决方案都与成本相关,我们正在寻找成本最低的最佳解决方案为了避免陷入局部最优,有时会选择两个后续解决方案中最差的一个。这样做的可能性取决于称为温度的控制参数。随着每一次迭代,温度降低,因此越来越不可能选择更差的解决方案。选择更差解的实际概率取自热力学。它是两种解决方案的成本差异除以温度乘以常数的指数。以下PCHR程序方案实现通用SA算法:%溶液(温度,溶液)solution(T,S)=>1:stop_criterion(T,S)|good_solution(S).solution(T,S)=>0:cool_down(T,T1)、gen_next_sol(S,S1)、anneal((T,S),(T1,S1))。FRUhwirth,DiPierro,Wiklicky123一个!2 1 122 1 2一个!212p1p1S退火((T,S),(T1,S1))=>1:溶液(T1,S1)。退火((T,S),(T1,S1))<=>>最大值C=成本(S),C1=成本(S1),e^((C1-C)/(k*T))-1:C1>C|溶液(T1,S)。3.3PCHR方案Conuence是(非概率)可编程的一个重要性质[2]。在一个并行程序中,无论实际应用哪一个可应用的规则,计算结果总是相同的我们回忆一下[2]中给出的基本定义。定义3.8如果存在状态T和T使得S!T和S T以及T和T是彼此的变体,即,它们可以通过变量重命名彼此获得定义3.9如果对所有状态S;S1;S2,下面的例子:如果S!S和S,则S和S是可连接的。给定一个PCHR程序,它的递归支持(或递归版本)由从规则中删除概率信息获得的递归程序给出。例如,对PCHR计划的支持c(X)<=>1:X>=0|a(X)。c(X)<=>2:X=< 0|b(X).由下式给出:c(X)<=> X>=0| a(X)。c(X)<=>X=< 0|b(X).这一概念以明显的方式概括为PCHR支持-grams:在一个并发的PCHR程序中,我们总是达到相同的结果,可能是通过不同的路径和不同的概率。定义3.10Two状态S1 和s2 如果符合以下条件,存在状态T1和t2苏chthatS1! T1和S2号!p2T2和T1和T2 是彼此的变体,即,它们可以从一个或另一个地方获得,变量重命名。定义3.11如果对于所有状态S;S1;S2, 的假设:如果S ! S! 2p2然后S1 和s2是可接合的。例如,上述PCHR程序是不连续的,因为X=0,c(X)可以导致X=0,a(X)(概率1=3)或X=0,b(X)(概率2=3)。很容易看出,任何有即时支持的PCHR程序都是和S1FRUhwirth,DiPierro,Wiklicky124我pi!本身是一致的。一般情况下,相反的情况并不成立,正如下面简单的PCHR程序所示:c(X)<=>1:X>=0|a(X)。c(X)<=>0:X>=0|b(X).这个程序(作为PCHR程序)是conuent:两个规则都有相同的保护,但是由于第二个规则的概率为零,因此只有第一个规则总是会被执行。然而,它的概率支持是不一致的:如果没有概率,两个规则都可能重写,因此我们可能最终得到不同的结果。如果我们考虑一个随机程序的所有可能的推导结果,|则这对应于考虑对应PCHR程序中所有规则的严格正概率。|then this corresponds to considering strictly positive probabilities for allrules in a corresponding PCHR program.换句话说,如果我们有S的支持, ! 则存在概率推导原始的PCHRS!Si换一些pi>0,反之亦然。 对于PCHR非零概率的程序,我们有:命题3.12如果PCHR程序P中的所有概率都是严格正的,则P是conuent,如果它的支持度是conuent。这意味着概率的引入并没有使并发的情况恶化:并发的程序在其概率版本中也是并发的。对于PCHR程序,我们可以定义一个概率连续的概念,它比连续的概念更“现实”,因为它允许我们忽略那些尽管可能但几乎从未执行过的计算(它们的概率为零)。请注意,这样的计算必须是在nite;事实上,由于非零数的(nite)乘积总是非零的,我们只能得到概率为零的nite乘积的极限。因此,非终止程序,这是经典的non-conuent可能导致conuent根据新的概念。定义3.13如果对于所有状态,S;S;S以下情况成立:如果SS和S! S然后S和S是1 2p11p22 1 2概率上可结合的。两个状态S1 和s2 PCHR计划的一部分,如果满足以下条件,存在状态T且T使得S!不 和S!不 和T和1 2 111 212 1T2 是彼此不同的。这意味着我们要求从初始状态S开始,所有导子将以概率1再次在相同(或在方差下等价)状态注意,这并不排除没有达到唯一(直到方差)状态的派生的存在,只要它们的概率为零,即它们是nite。FRUhwirth,DiPierro,Wiklicky125很容易看出,任何当前的PCHR程序也是概率上的。如果PCHR程序是一致的,则从初始状态S的所有推导将在某个唯一(直到方差)状态T处相遇。特别地,连续性要求不存在(nite或nite)达不到T的派生。这意味着,与导致T的每个导子的概率无关,它们都必须总和为1。然而,正如例3.5中实现一维随机游动的程序所示,相反的情况一般并不成立:它是概率上连续的(它总是在X=Y的状态下终止),但不是连续的(从状态X=Y=0,我们可以得到X=1,Y=0和X=0,Y=1,但它们是不可连接的)。4执行我们通过源代码到源代码程序转换(STS)实现了PCHR [10]。在STS中,用户将编写STS程序,以便在编译过程中操作其他程序。STS的核心思想是通过为规则的组成部分(头、保护、主体和编译器杂注)引入特殊的约束,将编译器规则转换为关系范式。STS程序是一个特殊用途的约束求解器,作用于这种表示。当到达xpoint时,关系形式被转换回XML规则,正常的编译继续。这种方法的结果是非常简单的STS程序。它们简洁、紧凑,因此易于检查和分析。事实上,实现概率排序的完整STS程序由几条规则组成,这些规则很容易在一个页面上实现。维也纳大学的ChristianHolzbaur在访问ThomFru慕尼黑路德维希-马克西米利安大学(Ludwig-Maximilians-University Munich)在我们看STS之前,我们通过一个例子来展示目标程序是如何该示例表明,PCHR可以用于生成n位随机数。更多PCHR的例子可以在[9]中找到。示例4.1[n比特随机数]随机数被表示为递归地并且逐个随机地生成的N比特的列表。r1@rand(N,L)<=>N=:=0 | L=[].r2@rand(N,L)<=>0.5:N>0 |L=[0| L1],rand(N-1,L1). r3@rand(N,L)<=>0.5:N>0 |L=[1| L1],rand(N-1,L1).只要有位要生成,下一位将得到值0或1,两者的概率相同。当剩余列表长度N为零时,非概率简化规则关闭列表。上述三个规则将被表示为STS程序将被应用于的FRUhwirth,DiPierro,Wiklicky126约束(rand/2),head(r1,rand(N,L),id1,remove),guard(r1,N=:=0),body(r1,L=[]),head(r2,rand(N,L),id2,remove),guard(r2,N>0),body(r2,(L=[0| L1],rand(N-1,L1),pragma(r2,0.5),head(r3,rand(N,L),id3,remove),guard(r3,N>0),body(r3,(L=[1| L1],rand(N-1,L1),pragma(r2,0.5).对于目标程序中的每一个STS约束符号,都有一个对应的STS约束.剩下的STS约束head、guard、body和pragma中的每一个都以它们所来自的规则的标识符开始。第二个参数是规则的相应组成部分对于约束头,第三个参数是与规则头匹配的约束的标识符,最后一个参数指示是保留还是删除约束。这些信息是必要的,因为任何类型的规则都是以相同的规范化的关系方式表示的。现在我们考虑PCHR的STS程序,它将以关系形式应用于上面的示例代码它只是说明了在规则是概率性的情况下,规则的组成部分应该如何下面的两个规则基本上定义了一个标准转换,它使对象规则的冲突集冲突集是适用于特定推导步骤的所有规则的集合。而在正常的排序中,任何规则都可以被选择,这是一个承诺的选择,在概率排序中,我们必须从冲突集中的所有候选人中收集未归一化的概率,然后根据它们的概率(权重)随机选择一个规则pragma(R,N),head(R,H,I,remove),body(R,G)<=>number(N)|pragma(R,N),head(R,H,I,keep),body(R,(remove_constraint(I),G)).pragma(R,N),body(R,G)<=> number(N)|body(R,cand(N,G)).rst转换规则将所有概率规则映射到传播规则中,这些规则使用标准的rst内置的remove约束显式地删除规则主体中的head约束。(同样的效果也可以使用辅助变量来实现,而不需要这个标准的内置变量,但它的效率会降低。第二个转换规则用运行时约束cand包装概率规则的主体,其rst参数是来自pragma的概率度量(权重)注意以文本顺序应用变换规则。最后但并非最不重要的是有一个nal,第三个规则添加了一个last object规则FRUhwirth,DiPierro,Wiklicky127对于每个定义的约束条件:constraint(C)==>头(R1,C,I,保持),保护(R1,真),体(R1,收集(0,_))。所得到的传播规则被添加在目标程序的末尾,并且仅调用触发适用概率规则主体的候选集合的概率归一化和评估的 约 束 条 件collect(0,)。对于我们的随机n位数的示例,STS规则的应用和最终转换回规则语法导致以下代码:r1@rand(A,B)#C< => A=:=0|B=[]。r2@rand(A,B)#C ==> A>0|cand(1,(remove_constraint(C),B=[0| D],rand(A-1,D)。r3@rand(A,B)#C ==> A>0|cand(1,(remove_constraint(C),B=[1| D],rand(A-1,D)。r4@rand(A,B)#C ==> collect(0,D).添加到规则头的#C是用于访问标识符的语法。与头部相匹配的约束。请注意,rst规则没有翻译,因为它不是概率性的。通过在用于PCHR的STS程序中定义并添加到变换目标程序的以下规则来实现候选集的概率归一化和评估collect(M,R),cand(N,G)<=>cand(R,M,M+N,G),collect(M+N,R). collect(M,R)<=> random(0,M,R).cand(R,M,M1,G)<=> R R >= M1|真的cand(R,M,M1,G)<=> M =
下载后可阅读完整内容,剩余1页未读,立即下载
cpongm
- 粉丝: 5
- 资源: 2万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- IPQ4019 QSDK开源代码资源包发布
- 高频组电赛必备:掌握数字频率合成模块要点
- ThinkPHP开发的仿微博系统功能解析
- 掌握Objective-C并发编程:NSOperation与NSOperationQueue精讲
- Navicat160 Premium 安装教程与说明
- SpringBoot+Vue开发的休闲娱乐票务代理平台
- 数据库课程设计:实现与优化方法探讨
- 电赛高频模块攻略:掌握移相网络的关键技术
- PHP简易简历系统教程与源码分享
- Java聊天室程序设计:实现用户互动与服务器监控
- Bootstrap后台管理页面模板(纯前端实现)
- 校园订餐系统项目源码解析:深入Spring框架核心原理
- 探索Spring核心原理的JavaWeb校园管理系统源码
- ios苹果APP从开发到上架的完整流程指南
- 深入理解Spring核心原理与源码解析
- 掌握Python函数与模块使用技巧
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功