`
61party
  • 浏览: 1124479 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Scala Tutorial中英对照:条件类和模式匹配

阅读更多

上一篇:Scala Tutorial中英对照:和Java交互,一切皆对象

这个文档,是翻译自官方的Scala Tutorial ,为了防止自己理解错误,保留原文以便参照。

由于篇幅所限,共分成三篇。

博客中格式不好调整,感兴趣的朋友可以下载PDF版本:http://download.csdn.net/source/1742639

---

6条件类和模式匹配 Case classes and pattern matching

树是软件开发中使用频率很高的一种数据结构,例如:解释器和编译器内部使用树来表示代码结构;XML文档是树形结构;还有一些容器(集合,containers)也是基于树的,比如:红黑树(red-black tree,一种自平衡二叉查找树)。

A kind of data structure that often appears in programs is the tree. For example, interpreters and compilers usually represent programs internally as trees; XML documents are trees; and several kinds of containers are based on trees, like red-black trees.

接下来,我们通过一个示例程序,了解在Scala中如何表示和操作树形结构,这个示例将实现非常简单的计算器功能,该计算器可以处理包含加法、变量和整数常量的算术表达式,比如:1 + 2、(x + x) + (7 + y)等。

We will now examine how such trees are represented and manipulated in Scala through a small calculator program. The aim of this program is to manipulate very simple arithmetic expressions composed of sums, integer constants and variables. Two examples of such expressions are 1 + 2 and (x + x) + (7 + y).

首先,我们要决定如何表示这样的表达式。最自然的选择是树形结构,用非叶子节点表示操作符(具体到这个例子,只有 加法操作),用叶子节点表示操作数(具体到这个例子是常量和变量)。

We first have to decide on a representation for such expressions. The most natural one is the tree, where nodes are operations (here, the addition) and leaves are values (here constants or variables).

如果是在Java中,建立树形结构最常见的做法是:创建一个表示树的抽象类,然后每种类型的节点用一个继承自抽象类的子类来表示。而在函数式编程语言中,则可以使用代数数据类型(algebraic data-type)来达到同样的目的。Scala则提供了一种介于两者之间(类继承和代数数据类型),被称为条件类(case classes)的概念,下面就是用条件类定义树的示例代码:

In Java, such a tree would be represented using an abstract super-class for the trees, and one concrete sub-class per node or leaf. In a functional programming language, one would use an algebraic data-type for the same purpose. Scala provides the concept of case classes which is somewhat in between the two. Here is how they can be used to define the type of the trees for our example:

abstract class Tree

case class Sum(l: Tree, r: Tree) extends Tree

case class Var(n: String) extends Tree

case class Const(v: Int) extends Tree

上例中的Sum, Var和Const就是条件类,它们与普通类的差异主要体现在如下几个方面:

The fact that classes Sum, Var and Const are declared as case classes means that they differ from standard classes in several respects:

· 新建条件类的实例,无须使用new关键字(比如,可以直接用Const(5)代替new Const(5)来创建实例)。

· the new keyword is not mandatory to create instances of these classes (i.e. one can write Const(5) instead of new Const(5)),

· 自动为构造函数所带的参数创建对应的getter方法(也就是说,如果c是Const的实例,通过c.v即可访问构造函数中的同名参数v的值)

· getter functions are automatically defined for the constructor parameters (i.e. it is possible to get the value of the v constructor parameter of some instance c of class Const just by writing c.v),

· 条件类都默认实现equals和hashCode两个方法,不过这两个方法都是基于实例的结构本身(structure of instance),而不是基于实例中可用于区分的值(identity),这一点和java中Object提供的同名方法的默认实现是基本一致的。

· default definitions for methods equals and hashCode are provided, which work on the structure of the instances and not on their identity,

· 条件类还提供了一个默认的toString方法,能够以源码形式(source form)打印实例的值(比如,表达式x+1会被打印成Sum(Var(x),Const(1)),这个打印结果,和源代码中创建表达式结构树的那段代码完全一致)。

· a default definition for method toString is provided, and prints the value in a “source form” (e.g. the tree for expression x+1 prints as Sum(Var(x),Const(1))),

· 条件类的实例可以通过模式匹配(pattern matching)进行分解(decompose),接下来会详细介绍。

· instances of these classes can be decomposed through pattern matching as we will see below.

既然我们已经定义了用于表示算术表达式的数据结构,接下来我们可以定义作用在这些数据结构上的操作。首先,我们定义一个在特定环境(environment,上下文)中对表达式进行求值的函数,其中环境的作用是为了确定表达式中的变量的取值。例如:有一个环境,对变量x的赋值为5,我们记为:{x → 5},那么,在这个环境上求x + 1的值,得到的结果为6。

Now that we have defined the data-type to represent our arithmetic expressions, we can start defining operations to manipulate them. We will start with a function to evaluate an expression in some environment. The aim of the environment is to give values to variables. For example, the expression x + 1 evaluated in an environment which associates the value 5 to variable x, written {x → 5}, gives 6 as result.

在程序中,环境也需要一种合理的方式来表示。可以使用哈希表(hash table)之类的数据结构,也可以直接使用函数(functions)!实际上,环境就是一个给变量赋予特定值的函数。上面提到的环境:{x → 5},在Scala中可以写成:

We therefore have to find a way to represent environments. We could of course use some associative data-structure like a hash table, but we can also directly use functions! An environment is really nothing more than a function which associates a value to a (variable) name. The environment {x → 5} given above can simply be written as follows in Scala:

{ case "x" => 5 }

上面这一行代码定义了一个函数,如果给该函数传入一个字符串"x"作为参数,则函数返回整数5,否则,将抛出异常。

This notation defines a function which, when given the string "x" as argument, returns the integer 5, and fails with an exception otherwise.

在写表达式求值函数之前,我们还要对环境的类型(type of the environments)进行命名。虽然在程序中全都使用String => Int这种写法也可以的,但给环境起名后,可以简化代码,并使得将来的修改更加方便(这里说的环境命名,简单的理解就是宏,或者说是自定义类型)。在Scala中,使用如下代码来完成命名:

Before writing the evaluation function, let us give a name to the type of the environments. We could of course always use the type String => Int for environments, but it simplifies the program if we introduce a name for this type, and makes future changes easier. This is accomplished in Scala with the following notation:

type Environment = String => Int

此后,类型名Environment可以作为“从String转成Int”这一类函数的别名。

From then on, the type Environment can be used as an alias of the type of functions from String to Int.

现在,我们来写求值函数。求值函数的实现思路很直观:两个表达式之和(sum),等于分别对两个表达式求值然后求和;变量的值直接从环境中获取;常量的值等于常量本身。在Scala中描述这个概念并不困难:

We can now give the definition of the evaluation function. Conceptually, it is very simple: the value of a sum of two expressions is simply the sum of the value of these expressions; the value of a variable is obtained directly from the environment; and the value of a constant is the constant itself. Expressing this in Scala is not more difficult:

def eval(t: Tree, env: Environment): Int = t match {

case Sum(l, r) => eval(l, env) + eval(r, env)

case Var(n) => env(n)

case Const(v) => v

}

求值函数的工作原理是对树t上的结点进行模式匹配,下面是对匹配过程的详细描述(实际上是递归):

This evaluation function works by performing pattern matching on the tree t. Intuitively, the meaning of the above definition should be clear:

1. 求值函数首先检查树t是不是一个求和(Sum),如果是,则把t的左子树和右子树分别绑定到两个新的变量l和r上,然后对箭头右边的表达式进行运算(实际上就是分别求左右子树的值然后相加,这是一个递归)。箭头右边的表达式可以使用箭头左边绑定的变量,也就是l 和 r。it first checks if the tree t is a Sum, and if it is, it binds the left sub-tree to a new variable called l and the right sub-tree to a variable called r, and then proceeds with the evaluation of the expression following the arrow; this expression can (and does) make use of the variables bound by the pattern appearing on the left of the arrow, i.e. l and r,

2. 如果第一个检查不满足,也就是说,树t不是Sum,接下来就要检查t是不是一个变量Var;如果是,则Var中包含的名字被绑定到变量n上,然后继续执行箭头右边的逻辑。if the first check does not succeed, that is if the tree is not a Sum, it goes on and checks if t is a Var; if it is, it binds the name contained in the Var node to a variable n and proceeds with the right-hand expression,

3. 如果第二个检查也不满足,那意味着树t既不是Sum,也不是Var,那就进一步检查t是不是常量Const。如果是,则将常量所包含的值赋给变量v,然后继续执行箭头右边的逻辑。if the second check also fails, that is if t is neither a Sum nor a Var, it checks if it is a Const, and if it is, it binds the value contained in the Const node to a variable v and proceeds with the right-hand side,

4. 最后,如果以上所有的检查都不满足,程序会抛出异常,表明对表达式做模式匹配时产生了错误。这种情况,在本例中,只有声明了更多Tree的子类,却没有增加对应的模式匹配条件时,才会出现。finally, if all checks fail, an exception is raised to signal the failure of the pattern matching expression; this could happen here only if more sub-classes of Tree were declared.

通过上例,我们可以看到,模式匹配的过程,实际上就是把一个值(value)和一系列的模式进行比对,如果能够匹配上,则从值(value)中取出有用的部件(parts)进行命名,然后用这些命名的部件(作为参数)来驱动另一段代码的执行。

We see that the basic idea of pattern matching is to attempt to match a value to a series of patterns, and as soon as a pattern matches, extract and name various parts of the value, to finally evaluate some code which typically makes use of these named parts.

一个有经验(seasoned,老练的)的面向对象程序员可能会问:为什么不把eval定义成类Tree的成员方法?事实上,这么做也行,因为在Scala中,条件类和普通类一样,都可以定义方法。不过,“模式匹配”和“类方法”除了编程风格的差异,也各有利弊,决策者需要根据程序的扩展性需求做出权衡和选择:

A seasoned object-oriented programmer might wonder why we did not define eval as a method of class Tree and its subclasses. We could have done it actually, since Scala allows method definitions in case classes just like in normal classes. Deciding whether to use pattern matching or methods is therefore a matter of taste, but it also has important implications on extensibility:

· 使用类方法,添加一种新的节点类型比较简单,因为只需要增加一个Tree的子类即可。但是,要在树上增加一种新的操作则比较麻烦,因为这需要修改Tree的所有子类。

· when using methods, it is easy to add a new kind of node as this can be done just by defining the sub-class of Tree for it; on the other hand, adding a new operation to manipulate the tree is tedious, as it requires modifications to all sub-classes of Tree,

· 使用模式匹配,情况则刚好相反:增加一种新的节点类型需要修改所有作用在树上的模式匹配函数;而增加新的操作则比较简单,只需要增加一个新的函数即可。

· when using pattern matching, the situation is reversed: adding a new kind of node requires the modification of all functions which do pattern matching on the tree, to take the new node into account; on the other hand, adding a new operation is easy, by just defining it as an independent function.

为了更深入的探索模式匹配,我们要在算术表达式上定义一个新的操作:对符号求导(symbolic derivation,导数)。该操作的规则如下:

To explore pattern matching further, let us define another operation on arithmetic expressions: symbolic derivation. The reader might remember the following rules regarding this operation:

1. 对和求导,等于分别求导的和。the derivative of a sum is the sum of the derivatives,

2. 对变量v求导,有两种情况:如果变量v正好是用于求导的符号,则返回1,否则返回0。the derivative of some variable v is one if v is the variable relative to which the derivation takes place, and zero otherwise,

3. 常量求导恒为0。the derivative of a constant is zero.

这几条规则几乎可以直接翻译成Scala的代码:

These rules can be translated almost literally into Scala code, to obtain the following definition:

def derive(t: Tree, v: String): Tree = t match {

case Sum(l, r) => Sum(derive(l, v), derive(r, v))

case Var(n) if (v == n) => Const(1)

case _ => Const(0)

}

通过求导函数的定义,又引出了两个跟模式匹配相关的知识点。第一、case语句可以带一个guard,它由关键字if和紧随其后的表达式组成。guard的作用是对case匹配的模式进行二次限定,只有if后面的表达式为true时,才允许匹配成功。在本例中,guard保证当且仅当被求导的变量名n等于当前求导符号v时,才返回常量1。第二、模式匹配中可以使用通配符(记为_,下划线)来匹配任意值(相当于java中switch语句的default分支)。

This function introduces two new concepts related to pattern matching. First of all, the case expression for variables has a guard, an expression following the if keyword. This guard prevents pattern matching from succeeding unless its expression is true. Here it is used to make sure that we return the constant 1 only if the name of the variable being derived is the same as the derivation variable v. The second new feature of pattern matching used here is the wild-card, written _, which is a pattern matching any value, without giving it a name.

模式匹配的功能非常强大,但限于本文的长度和定位,我们将不再做太多深入的讨论,接下来,我们还是通过一个实例,来看看前面定义的两个函数如何使用吧。为此,我们编写一个的main函数,在函数中,先创建一个表达式:(x + x) + (7 + y),然后在环境{x → 5, y → 7}上求表达式的值,最后分别求表达式相对于xy的导数。

We did not explore the whole power of pattern matching yet, but we will stop here in order to keep this document short. We still want to see how the two functions above perform on a real example. For that purpose, let’s write a simple main function which performs several operations on the expression (x + x) + (7 + y): it first computes its value in the environment {x → 5, y → 7}, then computes its derivative relative to x and then y.

def main(args: Array[String]) {

val exp: Tree = Sum(Sum(Var("x"),Var("x")),Sum(Const(7),Var("y")))

val env: Environment = { case "x" => 5 case "y" => 7 }

println("Expression: " + exp)

println("Evaluation with x=5, y=7: " + eval(exp, env))

println("Derivative relative to x:\n " + derive(exp, "x"))

println("Derivative relative to y:\n " + derive(exp, "y"))

}

执行这段程序,我们得到的输出如下:

Executing this program, we get the expected output:

Expression: Sum(Sum(Var(x),Var(x)),Sum(Const(7),Var(y))) Evaluation with x=5, y=7: 24

Derivative relative to x:

Sum(Sum(Const(1),Const(1)),Sum(Const(0),Const(0))) Derivative relative to y:

Sum(Sum(Const(0),Const(0)),Sum(Const(0),Const(1)))

仔细观察程序的输出,我们发现,如果把求导结果化简(simplification)后再展示给用户会更好。使用模式匹配来定义一个化简函数是很有意思(同时也很棘手)的事情,读者可以自己做做练习。

By examining the output, we see that the result of the derivative should be simplified before being presented to the user. Defining a basic simplification function using pattern matching is an interesting (but surprisingly tricky) problem, left as an exercise for the reader.

分享到:
评论

相关推荐

    Scala Tutorial 中英文对照

    2. **模式匹配**:Scala 提供了一种强大的模式匹配机制,可以通过模式匹配来进行条件判断和数据提取。 3. **集合**:Scala 提供了丰富的集合框架,包括不可变集合和可变集合,支持高效的集合操作。 4. **并发与...

    网络流量采样在高吞吐量链路异常检测中的应用研究

    内容概要:本文探讨了高吞吐量网络链路异常检测中流量采样技术的应用及其效果。面对现代分布式信息系统频繁遭受的网络安全威胁,特别是互联网服务提供商(ISP)面临的威胁,作者提出一种通过减少数据采样频率以降低异常检测计算复杂度的方法。文中介绍了实验环境、系统架构、采用的数据聚合与采样方法以及用于检测异常的人工智能模型(基于自编码器神经网络)。通过对一个真实中型ISP生产环境中实际网络流量数据进行研究,该研究展示了即使在较低采样频率情况下仍能保持较高的异常检测准确性,尤其是针对持续时间较长的DDoS攻击更为显著。此外,论文还验证了所提系统的有效性和应用潜力,为构建高效的网络安全监控机制提供了新思路。 适用人群:对于计算机网络安全、数据分析或机器学习有兴趣的研究人员和从业人员,特别是那些专注于提高异常检测性能和应对高流量数据流的技术人员。 使用场景及目标:适用于希望在不影响业务操作的前提下引入额外层次防护措施的企业级网络管理员;研究者可参考本文中提出的流量预处理方式来探索不同的统计分布和采样间隔设置;企业可以通过部署该类系统快速响应潜在的安全事件并降低成本。

    unity ui画线插件

    unity ui画线插件

    比例公平性的下行链路资源分配在基于OFDMA的中继网络中的应用与优化(可复现,有问题请联系博主)

    内容概要:本文研究了在基于正交频分多址接入(OFDMA)的中继网络中进行带有比例公平性的下行链路资源分配问题。作者们通过联合优化中继选择、子载波分配和功率分配问题,并采用拉格朗日对偶分解方法求解这一复杂的NP完全问题。实验结果显示所提出的算法相较于启发式算法能显著提高系统吞吐量,并带来更好的用户间公平性。 适合人群:通信工程、无线网络优化、电信行业研发工程师和研究人员。 使用场景及目标:主要应用于提升4G移动通信系统的频谱效率及缓解频率选择衰落的问题,确保多用户之间的传输速率更加公平。同时适用于研究OFDMA技术及其相关领域的学者和技术专家。 其他说明:文中提供了详细的数学模型和模拟结果图表支持理论发现,并讨论了各种假设条件下的性能对比。此外还探讨了连续松弛技巧在解决NP完全问题时的应用价值以及通过调整算法参数来获得近似最优解的方法论意义。

    [程序系统设计]MATLAB打印纸缺陷检测GUI(不同缺陷类型,GUI界面).zip

    程序系统设计]MATLAB打印纸缺陷检测GUI(不同缺陷类型,GUI界面) [程序系统设计]MATLAB打印纸缺陷检测GUI(不同缺陷类型,GUI界面) [程序系统设计]MATLAB打印纸缺陷检测GUI(不同缺陷类型,GUI界面) [程序系统设计]MATLAB打印纸缺陷检测GUI(不同缺陷类型,GUI界面) [程序系统设计]MATLAB打印纸缺陷检测GUI(不同缺陷类型,GUI界面)

    邮件分拣组态王6.55和西门子S7-200plc联机程序2023,带io表,运行效果视频 ,邮件分拣; 组态王6.55; 西门子S7-200plc; 联机程序2023; IO表; 运行效果视频,邮件

    邮件分拣组态王6.55和西门子S7-200plc联机程序2023,带io表,运行效果视频 ,邮件分拣; 组态王6.55; 西门子S7-200plc; 联机程序2023; IO表; 运行效果视频,邮件分拣组态王6.55与S7-200PLC联机程序2023版:带IO表运行效果视频

    基于关系变化和跨时间差异注意力机制的遥感影像变化检测(可复现,有问题请联系博主)

    内容概要:本文提出了一种新的基于跨时间差异(CTD)注意力机制的变化检测方法(称为CTD-Former),用于高效地提取多时相遥感图像中的变化特征。作者重新审视了自注意力机制并深入挖掘多时间相位图像间的关系变化,构建CTD变压器编码器和解码器来增强这些特征。此外,还引入了一致性感知模块(CPB)以保护变化区域的空间结构。实验结果显示,在LEVIR-CD、WHU-CD和CLCD数据集上,该模型相比于当前最优的方法表现出更好的性能。 适合人群:对深度学习、遥感图像处理、尤其是变化检测感兴趣的研究人员和技术专家,特别是熟悉变换器网络架构的从业者。 使用场景及目标:此方法适用于需要从多时相对比遥感影像中识别变化情况的任务,如环境监测、灾害评估、城市规划等领域内的应用开发,能够帮助研究者和决策者更准确地了解地面物体随时间的变化趋势。 其他说明:源代码可在GitHub仓库中获取,这为未来的研究提供了一个重要的参考平台,有助于推动该领域的进一步发展。

    [matlab程序系统设计]MATLAB的视频图像去雾(处理视频,GUI界面).zip

    该项目是个人实践项目,答辩评审分达到90分,代码都经过调试测试,确保可以运行!,可用于小白学习、进阶。 该资源主要针对计算机、通信、人工智能、自动化等相关专业的学生、老师或从业者下载使用,亦可作为期末课程设计、课程大作业、毕业设计等。 项目整体具有较高的学习借鉴价值!基础能力强的可以在此基础上修改调整,以实现不同的功能。 欢迎下载,欢迎沟通,互相学习,共同进步!提供答疑!

    temp_sh.zip

    fajslghjlghg

    2008-2020年各省每十万人口高等学校平均在校生数数据

    2008-2020年各省每十万人口高等学校平均在校生数数据 1、时间:2008-2020年 2、来源:国家统计j、统计nj 3、指标:行政区划代码、地区名称、年份、每十万人口高等学校平均在校生数 4、范围:31省

    毕业设计&课程设计 基于STM32单片机基于RFID的电动车停车管理系统(软件源码+硬件资料+部署教程+功能说明+演示视频),高分项目,开箱即用

    毕业设计&课程设计 基于STM32单片机基于RFID的电动车停车管理系统(软件源码+硬件资料+部署教程+功能说明+演示视频),高分项目,开箱即用 用户 分为老师 及 学生 管理员 管理员 登录 用户管理 电动车管理 车卡rfid 电动车进出记录 挂失申请列表 解冻申请列表 补办列表申请 用户(只能管理自己的车) 注册(注册的时候选身份,选择学生或者老师) 登录 个人信息查看 电动车管理 进出校记录 挂失申请 解冻申请 补办申请

    无人机辅助旅行商问题的深度强化学习求解方法研究(可复现,有问题请联系博主)

    内容概要:本文探讨了一种新的基于深度强化学习的方法来解决旅行商问题与无人机组合优化(Traveling Salesman Problem with Drone, TSP-D),针对当前无人机辅助卡车配送中面临的协同调度难题进行了改进。研究者提出一种混合模型(HM),整合了注意力编码器和长短期记忆网络(LSTM)解码器的优势,从而有效地记录了多个车辆的动作序列并实现了协调路径规划。该方法在各种测试用例上展现了卓越性能,并能显著提高大型问题实例的计算效率,同时在实际应用场景如最后一步送货中有潜在的巨大价值。 适合人群:对物流系统优化和无人机应用有兴趣的专业人士,特别是从事最后一公里交付方案设计和技术实施的研究人员及工程师。 使用场景及目标:本研究所提出的深度学习框架主要适用于城市环境中复杂条件下的车辆和无人驾驶飞行系统的共同优化配置,目的是为了找到最优的货物递送方案,在最短的时间内完成所有的客户服务任务并返回起点。 其他说明:实验结果显示该算法在随机位置数据集和现实情况中的优越性超过了现有传统算法,表明它不仅能在简单理想情况下发挥良好效果,同样可以在更为复杂的条件下表现出稳定的性能。

    生活垃圾处理费征收管理系统产品介绍

    北京中启航向科技发展有限公司开发的城市生活垃圾处理费智慧征管系统,是一个全方位、一体化的解决方案,旨在协助城市管理部门高效、准确地收取生活垃圾处理费。该系统利用先进的人工智能和数据分析技术,实现垃圾分类、计量和收费的智能化管理,提升城市环境卫生质量,同时优化行政资源,提高征收效率。

    水测试试纸行业剖析:欧洲是全球最大的市场,占40%的份额.pdf

    水测试试纸行业剖析:欧洲是全球最大的市场,占40%的份额.pdf

    《电力电子技术(第5版)》王兆安-第2章-电力电子器件

    《电力电子技术(第5版)》王兆安_第2章_电力电子器件

    基于STM32的直流电机加减速正反转控制串口输出控制系统(P 1100009-基于STM32的直流电机加减速正反转控制串口输出控制系统(PCB 原理图 报告 源代码 proteus lcd1602)

    基于STM32的直流电机加减速正反转控制串口输出控制系统(P 1100009-基于STM32的直流电机加减速正反转控制串口输出控制系统(PCB 原理图 报告 源代码 proteus lcd1602) 功能描述:基于STM32平台 1、实现了电机控制正转、反转的功能 2、实现了电机控制加速、减速的功能 3、实现了串口输出控制信息的功能 4、串口可以模拟WIFI 蓝牙 RS232 等带有串口的功能。 资料包含: 1、源代码工程文件 2、仿真工程文件 3、lunwen报告1W字以上 4、原理图工程文件 5、PCB工程文件 ,核心关键词:STM32、直流电机、加减速、正反转控制、串口输出、控制信息、WIFI、蓝牙、RS232、源代码工程文件、仿真工程文件、原理图工程文件、PCB工程文件。,基于STM32的电机串口控制综合系统(含正反转、加减速及多种串口通信功能)

    ZYNQ7010采集AD7768

    ZYNQ7010采集AD7768

    apollo 泊车轨迹优化代码 hybridastar+iaps平滑优化+obca平滑优化 第一个图是matlab绘制 后面的图是程序用sdl库绘制 ,apollo;泊车轨迹优化;hybridas

    apollo 泊车轨迹优化代码 hybridastar+iaps平滑优化+obca平滑优化 第一个图是matlab绘制 后面的图是程序用sdl库绘制 ,apollo;泊车轨迹优化;hybridastar;iaps平滑优化;obca平滑优化;Matlab绘制;SDL库绘制,基于Apollo的泊车轨迹优化:HybridA*算法+平滑优化技术的实现与展示

    乳酸链球菌素检验表格(食品添加剂食用香精质量验收记录表).docx

    乳酸链球菌素检验表格(食品添加剂食用香精质量验收记录表).docx

Global site tag (gtag.js) - Google Analytics