【GreatSQL优化器-04】贪婪搜索算法浅析

人工智能--贪婪算法(启发式搜索) 贪婪算法是启发式算法的代表算法之一,其核心思想是每次都选择局部最优解,但该算法并不能保证最后得出的结果是全局最优解。贪婪算法比较典型的案例就是最短路径搜索。之前,大部分的贪婪算法都是基于图的方式寻找最优路径。本篇文章主要借助路径动态规划的案例利用贪婪算法讲解树的最优路径。 相对于图来说,在树的搜索过程中,贪婪算法会遇到很多不可行解,这就需要程序能否返回到最近的一个节点,重新寻找其他的可行路径。下面通过一个示例说明贪婪最佳优先搜索和改进贪婪优化算法具体过程。 问题描述 下图展示了城市之间的路径图,该图包含了城 阅读详情

【GreatSQL优化器-04】贪婪搜索算法浅析

一、贪婪搜索(greedy_search)介绍

GreatSQL的优化器用greedy_search方法来枚举所有的表连接场景,然后从中根据最小cost来决定最佳连接顺序。这里面就涉及每种场景的cost计算方法,不同计算方法会导致不同的排序结果。

因为枚举所有join场景,当表数量很大的时候就有可能无穷无尽消耗系统资源,因此GreatSQL执行greedy_search的时候使用search_depth 和prune_level变量(分别对应GreatSQL中的 optimizer_search_depth 和 optimizer_prune_level 系统变量),防止无穷无尽的分析各种连接顺序的成本,如果连接表的个数小于search_depth,那么就继续穷举分析每一种连接顺序的cost,否则只对与optimizer_search_depth 值相同数量的表进行穷举分析。该值越大,成本分析的越精确,越容易得到好的执行计划,但是消耗的时间也就越长,否则得到的可能不是最好的执行计划,但可以省掉很多分析连接成本的时间。设置合适的 prune_level 值可以裁剪掉一些不必要的深度,直接跟后面访问数量最少的表进行连接计算。

执行greedy_search复杂度可能是O(N*N^search_depth/search_depth)。如果search_depth > N 那么算法的复杂度就是 O(N!)。通常优化器分析的复杂度都是 O(N!)。

名称场景值
search_depththd->variables.optimizer_search_depth>0 (默认62)thd->variables.optimizer_search_depth
thd->variables.optimizer_search_depth=0表数量<=7,值为表数量+1
表数量>7,值为7
prune_level在设置了参数prune_level(默认设置)后,不再使用穷举的方式扩展执行计划,而是在剩余表中直接选取访问最少纪录数的表计算。如果未设置,则继续跟后面的表连接计算cost获取"最优"的执行计划。因此设置为on的时候执行复杂度小更快。thd->variables.optimizer_prune_level 值为0和1,默认值为1

下面用一个简单的例子来说明greedy_search是什么。

CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT,date1 DATETIME);
INSERT INTO t1 VALUES (1,10,'2021-03-25 16:44:00.123456'),(2,1,'2022-03-26 16:44:00.123456'),(3,4,'2023-03-27 16:44:00.123456'),(5,5,'2024-03-25 16:44:00.123456');
CREATE TABLE t2 (cc1 INT PRIMARY KEY, cc2 INT);
INSERT INTO t2 VALUES (1,3),(2,1),(3,2),(4,3),(5,15);
CREATE TABLE t3 (ccc1 INT, ccc2 varchar(100));
INSERT INTO t3 VALUES (1,'aa1'),(2,'bb1'),(3,'cc1'),(4,'dd1'),(null,'ee');
CREATE INDEX idx1 ON t1(c2);
CREATE INDEX idx2 ON t1(c2,date1);
CREATE INDEX idx2_1 ON t2(cc2);
CREATE INDEX idx3_1 ON t3(ccc1);

-- 这里做了一个6张表的连接,这里面就涉及了greedy_search方法来决定哪张表先执行哪张表后执行
-- 看下面最终结果是按照t1,t4,t2,t5,t3,t4顺序来执行连接的
greatsql> EXPLAIN SELECT * FROM t3,t1,t2,t1 AS t4,t2 AS t5,t3 AS t6 WHERE t1.c1=t3.ccc1 and t2.cc1=t3.ccc1 and t1.c1=t4.c1 and t1.c1=t5.cc1 and t1.c1=t6.ccc1;
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------------+
| id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref       | rows | filtered | Extra       |
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------------+
|  1 | SIMPLE      | t1    | NULL       | index  | PRIMARY       | idx2    | 11      | NULL      |    4 |   100.00 | Using index |
|  1 | SIMPLE      | t4    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t2    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t5    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t3    | NULL       | ref    | idx3_1        | idx3_1  | 5       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t6    | NULL       | ref    | idx3_1        | idx3_1  | 5       | db1.t1.c1 |    1 |   100.00 | NULL        |
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------------+
二、greedy_search代码解释
bool JOIN::make_join_plan() {
  // Choose the table order based on analysis done so far.
  if (Optimize_table_order(thd, this, nullptr).choose_table_order())
    return true;
}

bool Optimize_table_order::choose_table_order() {
  // 先对所有表做一个排序,小表放前面
  merge_sort();
  if (straight_join)
    optimize_straight_join(join_tables);
  else {
    if (greedy_search(join_tables)) return true;
  }
}

bool Optimize_table_order::greedy_search(table_map remaining_tables) {
  do {
    if (best_extension_by_limited_search(remaining_tables, idx, search_depth))
      return true;
    // 如果层数没有超过规定大小,说明已经执行完枚举可以退出。如果超过了,说明不需要执行枚举连接,按照单独连接方式继续执行。
    if (size_remain <= search_depth || use_best_so_far) {
      return false;
    }
    --size_remain;
    ++idx;
  }
}

// 用current_search_depth来计数,每进行一次深度连接计算就减一,用来控制join连接枚举分析的层数。
bool Optimize_table_order::best_extension_by_limited_search(
    table_map remaining_tables, uint idx, uint current_search_depth) {
  for (JOIN_TAB **pos = join->best_ref + idx; *pos && !use_best_so_far; pos++) {
      /* Find the best access method from 's' to the current partial plan */
      // 该表之后的每个表遍历一遍,计算每种连接的cost
      best_access_path(s, remaining_tables, idx, false,
                       idx ? (position - 1)->prefix_rowcount : 1.0, position);
      // 如果算完左连接cost比之前的还大,就不继续算下一张表,直接开始下一次连接计算
      if (position->prefix_cost >= join->best_read &&
          found_plan_with_allowed_sj) {
        trace_one_table.add("pruned_by_cost", true);
        continue;
      }
      // 打开裁剪模式的话
      if (prune_level == 1) {
        // 如果当前计算出来的rowcount小于之前保存下来的best_rowcount,那么就替换best_rowcount值
        if (best_rowcount > position->prefix_rowcount ||
            best_cost > position->prefix_cost ||
            (idx == join->const_tables &&  // 's' is the first table in the QEP
             s->table() == join->sort_by_table)) {
            best_rowcount = position->prefix_rowcount;
            best_cost = position->prefix_cost;
         } else // 否则就跳过剩下表的穷举搜索计算,直接用下一次连接继续计算
           continue;
      }
      // current_search_depth还在层数允许范围内,递归继续进行下一次优化查询
      if ((current_search_depth > 1) && remaining_tables_after) {
        if (prune_level == 1 &&             // 1)
            position->key != nullptr &&     // 2)
            position->rows_fetched <= 1.0)  // 3)
        {
          // 如果连接左表cost比之前的大,那么会被裁剪
          // 如果满足(EQ_)REF key的join方式并且本次找到的行数只有一行,那么就执行EQ_REF-joined连接计算
          eq_ref_extension_by_limited_search();
        } else
          // 继续执行下一张连接表的连接cost计算
          best_extension_by_limited_search(remaining_tables_after, idx + 1,
                                             current_search_depth - 1));
      } else  // if ((current_search_depth > 1) && ... // 层数还有剩,后面没有表要连接了,那就保存当次计算结果以便下次做比较
      {  // 将这次计算出来的rowcount和read_cost存入prefix_rowcount和prefix_read_cost,方便下一次连接比较cost
        // 如果此次join的cost更小,那么保存到join->best_read 和 join->best_rowcount
        if (consider_plan(idx, &trace_one_table)) return true;
      }
  }
}

void Optimize_table_order::best_access_path(JOIN_TAB *tab,
                                            const table_map remaining_tables,
                                            const uint idx, bool disable_jbuf,
                                            const double prefix_rowcount,
                                            POSITION *pos) {
  // 如果根据前面的结果keyuse_array数组有值的话,那么根据find_best_ref()函数先找出最优索引,按照索引的方式计算cost
  if (tab->keyuse() != nullptr &&
      (table->file->ha_table_flags() & HA_NO_INDEX_ACCESS) == 0)
    best_ref =
        find_best_ref(tab, remaining_tables, idx, prefix_rowcount,
                      &found_condition, &ref_depend_map, &used_key_parts);
  // 最主要计算下面3个值
  pos->filter_effect = filter_effect = std::min(1.0, tab->found_records * calculate_condition_filter() / rows_after_filtering);
  pos->rows_fetched = rows_fetched = rows_after_filtering;
  pos->read_cost = scan_read_cost = calculate_scan_cost();    
}

优化器内部有一些优化可以根据需要自己重新定义行为,这就涉及到optimizer_switch开关的设置。详细可以设置的optimizer_switch如下表所示,以后每个专门开一期细讲。

附表:优化器涉及的OPTIMIZER_SWITCH表

OPTIMIZER_SWITCH默认说明
OPTIMIZER_SWITCH_INDEX_MERGEON可以在多个索引上进行查询,并将结果合并返回。
OPTIMIZER_SWITCH_INDEX_MERGE_UNIONOFF会在使用到的多个索引上同时进行扫描,并取这些扫描结果的并集作为最终结果集。
OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNIONON比单纯的Union索引合并多了一步对二级索引记录的主键id排序的过程。
OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECTON会在使用到的多个索引上同时进行扫描,并取这些扫描结果的交集作为最终结果集。
OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWNON只用于NDB引擎,开启后时按照WHERE条件过滤后的数据发送到SQL节点来处理,不开启所有数据节点的数据都发送到SQL节点来处理
OPTIMIZER_SWITCH_INDEX_CONDITION_PUSHDOWNON当ICP打开时,用于二级索引的range、 ref、 eq_ref或ref_or_null扫描,如果部分where条件能使用索引的字段,server会把这部分下推到引擎层,可以利用index过滤的where条件在存储引擎层进行数据过滤。
OPTIMIZER_SWITCH_MRRON针对多列索引,也叫组合索引来做基本扫描,然后对匹配的记录按照主键排序,这样按照有序的主键顺序从磁盘上扫描需要的全部记录。根本功能是把对磁盘的随机扫描转化为顺序扫描。
OPTIMIZER_SWITCH_MRR_COST_BASEDONcost base的方式还选择启用MRR优化,当发现优化后的代价过高时就会不使用该项优化
OPTIMIZER_SWITCH_BNLON块嵌套循环(Block Nested Loop, BNL),将驱动表的数据先缓存在join buffer中,一次读取被驱动表的数据,可以和驱动表的多条记录进行join,这样就可以减少全表扫描的次数。
OPTIMIZER_SWITCH_BKAOFF批量索引访问(Batched Key Access),主要适用于join的表上有索引可利用,无索引只能使用BNL.多表join语句,被join的表/非驱动表必须有索引可用,才能利用BKA.对于多表join语句,当MySQL使用索引访问第二个join表的时候,使用一个join buffer来收集第一个操作对象生成的相关列值
OPTIMIZER_SWITCH_SEMIJOINON是否启用semijoin
OPTIMIZER_SWITCH_MATERIALIZATIONONOPTIMIZER_SWITCH_SEMIJOIN=ON,把内表去重然后生成有对应索引的临时表(有点类似其他数据中的物化视图),然后通过外表的对应键值遍历这张临时表。
OPTIMIZER_SWITCH_LOOSE_SCANONOPTIMIZER_SWITCH_SEMIJOIN=ON,把inner-table数据基于索引进行分组,取每组第一条数据进行匹配。
OPTIMIZER_SWITCH_FIRSTMATCHONOPTIMIZER_SWITCH_SEMIJOIN=ON,只选用内部表的第1条与外表匹配的记录。
OPTIMIZER_SWITCH_DUPSWEEDOUTONOPTIMIZER_SWITCH_SEMIJOIN=ON,使用临时表对semi-join产生的结果集去重
OPTIMIZER_SWITCH_SUBQ_MAT_COST_BASEDONOPTIMIZER_SWITCH_MATERIALIZATION=ON的时候,如果此项为ON选择CANDIDATE_FOR_IN2EXISTS_OR_MAT策略,否则选择SUBQ_MATERIALIZATION策略
OPTIMIZER_SWITCH_USE_INDEX_EXTENSIONSON索引扩展使用,主要用于INNODB的第二索引,也就是普通的索引,把索引中包含的主键值利用到。比如主键为(a,b),索引为(c). 如果用到了索引c,那么把索引变成(c,a,b) 这样,就可以用到新的组合索引了。不过这种场合用的也比较少,一般是根据组合主键中的第一个字段和普通索引一起来做检索的时候。
OPTIMIZER_SWITCH_COND_FANOUT_FILTERONjoin时候是否使用条件过滤百分比
OPTIMIZER_SWITCH_DERIVED_MERGEON派生表合并,类似Oracle的视图合并,当派生SQL中存在以下操作是无法展开:UNION 、GROUP 、DISTINCT、LIMIT及聚合操作
OPTIMIZER_SWITCH_USE_INVISIBLE_INDEXESOFF是否使用不可见索引
OPTIMIZER_SKIP_SCANON使用skip scan方式进行范围扫描,当要查询的列都在索引中时,即使where中的条件不是索引的第一部分,也可以使用索引。
OPTIMIZER_SWITCH_HASH_JOINON使用hash join方法,导致开销更大,已经弃用
OPTIMIZER_SWITCH_SUBQUERY_TO_DERIVEDOFF子查询转换为派生表
OPTIMIZER_SWITCH_PREFER_ORDERING_INDEXON对于 limit N 带有 group by ,order by 的 SQL 语句 (order by 和 group by 的字段有索引可以使用),执行计划选择 where 条件中的索引查找过滤数据,而不是根据order by id 的索引进而导致全表扫描
OPTIMIZER_SWITCH_HYPERGRAPH_OPTIMIZEROFF使用超图理论(Hypergraph Theory)来优化查询计划
OPTIMIZER_SWITCH_DERIVED_CONDITION_PUSHDOWNON对于派生表(DERIVED)的条件下推,即在执行派生表之前应用条件,减少在派生表中处理的数据量。
OPTIMIZER_SWITCH_FAVOR_RANGE_SCANOFF当index dive不能被跳过的时候,如果此项=ON,那么cost值*0.1
OPTIMIZER_SWITCH_REMOVE_USELESS_OUTERJOINOFF用于控制优化器在处理不必要的外连接时的行为。不必要的外连接指的是那些永远不会返回任何内连接行的连接。这些外连接在查询执行时会被优化器移除。
三、实际例子说明

接下来看几个例子来说明上面的代码。

greatsql> EXPLAIN SELECT * FROM t3,t1,t2,t1 AS t4,t2 AS t5,t3 AS t6 WHERE t1.c1=t3.ccc1 and t2.cc1=t3.ccc1 AND t1.c1=t4.c1 AND t1.c1=t5.cc1 AND t1.c1=t6.ccc1;
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------------+
| id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref       | rows | filtered | Extra       |
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------------+
|  1 | SIMPLE      | t1    | NULL       | index  | PRIMARY       | idx2    | 11      | NULL      |    4 |   100.00 | Using index |
|  1 | SIMPLE      | t4    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t2    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t5    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t3    | NULL       | ref    | idx3_1        | idx3_1  | 5       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t6    | NULL       | ref    | idx3_1        | idx3_1  | 5       | db1.t1.c1 |    1 |   100.00 | NULL        |
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------------+

-- 看一下枚举顺序:
"`t1`" -> `t1` `t4` -> `t3`
                    -> `t2` -> `t3`
                            -> `t2` `t5` -> `t3`
                                         -> `t3` `t6` -- cost太大不继续计算下一张表,直接开始下一次连接计算
                                         -> `t3` -> `t3` `t6`
       -> `t3`   
       -> `t3` `t6`  
`t1` `t4` -> `t1` -> `t3`
                  -> `t2` -> `t3`
                          -> `t2` `t5` -> `t3` 
                                       -> `t3` `t6` cost太大不继续计算下一张表,直接开始下一次连接计算
                                       -> `t3` -> `t3` `t6` cost太大不继续计算下一张表,直接开始下一次连接计算
后面类似,因为太多不写出来了。


-- 层数改为1,看看效果。
greatsql> set optimizer_search_depth=1;

-- 发现表的连接顺序跟之前不一样了。
greatsql> explain SELECT * FROM t3,t1,t2,t1 as t4,t2 as t5,t3 as t6 where t1.c1=t3.ccc1 and t2.cc1=t3.ccc1 and t1.c1=t4.c1 and t1.c1=t5.cc1 and t1.c1=t6.ccc1;
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------------+
| id | select_type | table | partitions | type   | possible_keys | key     | key_len | ref       | rows | filtered | Extra       |
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------------+
|  1 | SIMPLE      | t1    | NULL       | index  | PRIMARY       | idx2    | 11      | NULL      |    4 |   100.00 | Using index |
|  1 | SIMPLE      | t4    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t3    | NULL       | ref    | idx3_1        | idx3_1  | 5       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t2    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t5    | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | db1.t1.c1 |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | t6    | NULL       | ref    | idx3_1        | idx3_1  | 5       | db1.t1.c1 |    1 |   100.00 | NULL        |
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------+------+----------+-------------+

`t1` cost最小,选这个继续走
`t1` `t4`
`t3`
`t2`
`t2` `t5`
`t3` `t6`
`t1` -> `t1` `t4` -> `t3` -> `t2` -> `t2` `t5` -> `t3` `t6` cost最小,选这个继续走
                                  -> `t3` `t6`
                          -> `t2` `t5`
                          -> `t3` `t6`
                  -> `t2` 
                  -> `t2` `t5`
                  -> `t3` `t6`
     -> `t3`
     -> `t2`
     -> `t2` `t5`
     -> `t3` `t6`
四、总结

从上面优化器的步骤我们认识了贪婪算法的过程,知道了2个基本参数search_depth和prune_level,这两个参数可以自定义设置值用来简化算法的步骤,减少资源的消耗,但是也会相应的导致最后结果不精确,所以还是要按照个人需求进行设置。

Enjoy GreatSQL :)

关于 GreatSQL

GreatSQL是适用于金融级应用的国内自主开源数据库,具备高性能、高可靠、高易用性、高安全等多个核心特性,可以作为MySQL或Percona Server的可选替换,用于线上生产环境,且完全免费并兼容MySQL或Percona Server。

相关链接: GreatSQL社区 Gitee GitHub Bilibili

GreatSQL社区:

image

社区有奖建议反馈: https://greatsql.cn/thread-54-1-1.html

社区博客有奖征稿详情: https://greatsql.cn/thread-100-1-1.html

(对文章有疑问或者有独到见解都可以去社区官网提出或分享哦~)

技术交流群:

微信&QQ群:

QQ群:533341697

微信群:添加GreatSQL社区助手(微信号:wanlidbc )好友,待社区助手拉您进群。

greedy search和beam search的原理以及实现 在自然语言处理seq2seq模型中,模型训练完成后,预测推理时需要预测每一步输出的最可能的单词,之后组合成完整的预测输出句子。这里每一步最可能的输出单词的选择就用到greedy search或者beam search。下面详细介绍一下这两种搜索的区别,以及实现方法。 贪婪搜索 greedy search greedy search比较简单,就是贪婪式的搜索,每一步都选择概率最大的单词输出,最后组成整个句子输出。这种方法给出的结果一般情况结果比较差,因为只考虑了每一步的最优解,往往里全局最优解差距很大。 贪婪 阅读详情

相关推荐

【SOFA】SOFA框架+Win10+VS2019 配置

SOFA (Simulation Open Framework Architecture)官网 SOFA 是一个开源的仿真框架,用于实时的物理仿真,而且主要针对医学上的仿真。主要用于研究人员开发新的算法,也可以作为一个有效的快速成型工具或是物理引擎。 官网中给出的配置方法写的很清晰,有着各个库或者软件的版本要求,仔细看按版本要求来 官网配置地址 官网给了两种方 1.通过脚本自动配置 2. 自己下载相关库通过CMake进行生成 第一种 没使用,不知道是否好使,因为如果其中有下载的东西,国内不一定能成功,大家可

GordonWei 5260

小学生也能听得懂的大模型 - Transformer 1

参考 [小学生也能听得懂的大模型 Transformer 1]

2401_85325557的博客 1737

Dr_can Kalman Filter学习笔记(一)

本文是在b站Dr_can的卡尔曼滤波课程学习过程中的学习笔记

苏大侠的博客 1051

[算法与人生] 之 贪婪搜索

贪婪算法在具备最优子结构和贪心选择性质的问题上非常有效,能够提供高效且简单的解法。然而,对于缺乏这些特性的复杂问题,贪婪算法则可能无法找到最优解,甚至会导致错误的结果。在使用贪婪算法时,需要仔细分析问题的结构和性质,以判断其适用性。

具身机器人和通用AI 1256

图解移动机器人中的运动规划(Motion Planning),附几十种规划算法

运动规划是移动机器人的核心理论和工程技术之一,本文作为教程先导,解析了运动规划的两大组件——路径规划和轨迹规划。欢迎感兴趣的同学订阅专栏!

FRIGIDWINTER的博客 4万+

AUTOSAR进阶图解==>AUTOSAR_SWS_CANNetworkManagement

本文介绍了AUTOSAR架构中的CAN网络管理(CanNm)模块,主要内容包括: 模块概述:CanNm是协调CAN网络节点状态转换的基础组件,采用去中心化设计,通过周期性发送网络管理PDU保持网络活跃状态,支持网络唤醒、睡眠和部分网络功能。 架构设计:CanNm位于AUTOSAR中间层,连接上层通信管理器(ComM)和底层CAN接口(CanIf),包含状态管理、PDU处理和定时器管理等子组件。 状态机设计:定义了三种主要模式(总线睡眠、准备睡眠和网络模式)及其转换逻辑,网络模式又包含重复消息、正常操作和准备

一名留德华的,康德的信徒的,专注于汽车电子领域的博客 2041

解码策略详解:贪婪搜索、束搜索与Top-k采样

本文解析了文本生成中的三种主流解码策略。贪婪搜索选择概率最高的词元,效率高但缺乏多样性;束搜索通过维护多个候选序列提高质量,但计算成本增加;Top-k采样在概率最高的k个词元中随机选择,平衡质量与多样性。不同策略适用于不同场景的选择,需权衡质量、多样性和计算效率。文章详细介绍了每种策略的原理、实现方式及优缺点比较。

862

【人工智能】 WebDev Arena:实时AI Web开发竞赛的技术探索与价值

《AI编程竞赛推动Web开发技术创新》摘要:WebDev Arena作为聚焦Web开发领域的实时AI编程竞赛,通过标准化竞技环境检验AI模型在代码生成、问题解决等方面的能力。竞赛覆盖前端、后端等全流程开发环节,采用实时评分机制,推动AI对复杂Web需求的理解和多元技术栈适配。该赛事不仅促进AI编程技术创新,更为Web开发行业与AI技术融合搭建桥梁,有望提升开发效率、降低技术门槛。未来将拓展Web3.0等前沿技术主题,持续推动行业智能化发展。(150字)

奶爸的编程之路,也就一周冷个三天 255

[AI]贪婪最佳优先搜索 Greedy Best-First Search

贪婪最佳优先搜索 Greedy Best-First Search一、算法原理二、算法应用三、算法性能 一、算法原理 所谓贪婪,即只扩展当前代价最小的节点(或者说离当前节点最近的点)。这样做的缺点就是,目前代价小,之后的代价不一定小,如果解在代价最大的点,那么按照贪婪最佳优先算法,可能就找不到这个解,然后就会陷入死循环。 公式表示为: f(n)=h(n)f(n)=h(n)f(n)=h(n) h(n)h(n)h(n)代表当前节点到目标节点的最短距离。 二、算法应用 我们来举个例子实际应用一下该算法。 著名的R

土豆大叔的博客 1万+

Autosar软件组件分析及ARXML文件分析

Autosar软件组件分析及ARXML文件分析

专注汽车软件开发、AutoSAR、车载以太网、SOA、EE架构。 3601

【软考高级系统架构论文】论微服务架构及其应用

本文围绕“论微服务架构及其应用”展开论述。首先概要介绍了本人参与的某公司线上电子商务平台项目,在其中担任系统架构设计师。接着分析了微服务架构相较于单块架构的特点,如模块化与组件化、技术栈多样性、独立部署与扩展、高度容错与可用性等。最后结合项目阐述了软件架构对微服务模式的采用情况,以及实施过程中遇到的问题及解决方案,如服务划分粒度、数据一致性、监控与故障排查等问题,并给出了相应解决办法。

qq837993702的博客 225

GreatSQL社区2024年全年总结(免费领红包封面)

* GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。社区2024年总结GreatSQL 社区在2024年度上持续迈进,成果斐然。一方面,开放了 GreatSQL 单机版以及三节点 MGR 集群的在线测试体验环境,让用户能够在线体验各种 GreatSQL 创新特性。另一方面,社区手册也持续更新,方便用户查阅。同时,社区积极拓展教育合作领域,成功走进郑州大学,联合开设 “G...

老叶茶馆 195

STM32开发 -- GPIO详解

之前有简单讲过GPIO工作模式和寄存器,还是有点没搞明白。这次需要全方位的看一下了。 一、数据手册 1、STM32F105RC引脚说明 可知:STM32F105RC 一共有4组IO口 一共16X3+3=51个IO GPIOA0~A15 GPIOB0~B15 GPIOC0~C15 GPIOD0~D2 2、程序定义 GPIO端口号 STM32F1...

不积跬步,无以至千里 5万+

贪心算法、贪心搜索/采样(greedy search/sampling)、集束搜索(beam search)、随机采样(random sample)

的结果也是最好/最优的解。{看着这个名字,贪心,贪婪这两字的内在含义最为关键。这就好像一个贪婪的人,他事事都想要眼前看到最好的那个,看不到长远的东西,也不为最终的结果和将来着想,贪图眼前局部的利益最大化,有点走一步看一步的感觉。

Drug discovery 5871

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【AI】启发式搜索:贪婪最佳优先搜索与A*原理及python代码实现

【AI】启发式搜索:贪婪最佳优先搜索(Greedy best-first search)原理及python代码实现 搜索算法:启发式搜索 搜索算法的形式化描述:状态、动作、状态转移、路径、测试目标 **状态:**从原问题转化出的问题描述; 动作:从当前时刻所处状态转移到下一时刻所处状态所进行操作,一般而言这些操作都是离散的; 状态转移:对某一时刻对应状态进行某一种操作后,所能够到达状态; 路径:一个状态序列,该状态序列被一系列操作所连接; 测试目标: 新的改变 我们对Markdown编辑器进行了一些功能拓展

风巽·剑染春水的博客 1万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

启发式搜索 (Heuristically Search)-【贪婪最佳优先搜索】和【A*搜索】

  搜索是人工智能里面研究的一个核心问题,像强化学习其本质我也是理解为一种搜索算法,不过其用了一些值函数近似的方法,并做了进一步改良,使其功能更加强大。近些年来也有非常多学术研究者慢慢开始将两者融汇贯通发顶会了。比如像Goog的planet,Muzero以及将熵用于蒙特卡洛树搜索中平衡探索和利用的关系等等。 启发式搜索   启发式搜索(Heuristically Search)又称为有信息搜索(I...

小小何先生的学习之旅 2万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Python算法之贪婪最佳优先搜索(GBFS)

然后,从队列 queue 中取出当前最优的节点 (即最短路径的终点),并判断该节点是否已经访问过。同时,将当前节点到目标节点的边加入路径列表 path 中,并将该节点的未访问邻居节点加入队列 queue 中。首先,将起始节点 start 加入队列 queue 中,并将其加入已访问节点集合 visited 中。GBFS 算法在许多实际应用中都有广泛的应用,比如在计算机图形学中用于寻找两个三角形之间的最短路径,在自然语言处理中用于寻找最优的句子分割方案等等。最后,判断是否找到了目标节点。否则,返回 None。

weixin_59365912的博客 1382

贪心算法 Greedy Algorithm

一般来说,对于规模较小的问题,贪心算法的时间复杂度可以达到O(nlogn)或O(n^2);答:一个问题如果可以用递归的方式分解成若干个子问题,且每个子问题都有明确的最优解(即局部最优),那么这个问题就可以用贪心算法解决。贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。背包问题:给定一组物品和一个背包,每个物品有一定的重量和价值,要求在不超过背包容量的情况下,尽可能多地装入物品。找零问题:给定一定数量的硬币和需要找零的金额,求使用最少的硬币数。

2301_79602614的博客 1863

【算法】贪婪算法(贪心算法)

贪心算法是寻找最优解问题的常用方法。  这种方法模式一般将求解过程分成若干个步骤,在每个步骤都应用贪心原则,选取当前状态下最好的或最优的选择(局部最有利的选择),并以此希望最后对跌出的结果也是最好的或最优的解。  贪心算法的每次决策都以当前情况作为基础并根据某个最有原则进行选择,不从整体上考虑其他各种可能的情况。  贪心算法。动态规划法、分治法都是对问题进行分解,定义最优解的子结构.  贪心算法与...

Twinkle 9186

大模型(LLM)解码:从Greedy Search到Top-P

LLM意为大型语言模型。ChatGPT就是一种LLM,作为一种人工智能技术,通过使用深度学习算法来处理和生成自然语言文本,这些模型通常需要大量的数据来训练,以便能够理解和生成人类语言。

Mike0010的博客 6668

【人工智能】Java实现贪婪最佳优先搜索(Greedy Best-first Search)

1.原理 无信息搜索策略(Uninformed Search Strategies)是盲目的,不是很有效,当然也没有除问题定义的状态信息外的额外信息。而有信息搜索策略(Informed Search Strategies)提供了一些额外的信息,如到达目标的直线距离等,因此有信息搜索策略能更有效地进行问题求解。 最佳优先搜索(Best-first Search)使用评估函数f(n)(一般使用启发...

obestboy的专栏 6662

基于Python的自然语言处理系列(40):大型语言模型中的解码策略

在这篇文章中,我们探索了 Huggingface 提供的几种主要解码策略,包括贪婪搜索、束搜索、Top-K 采样和核采样。这些方法各有优势,适用于不同类型的文本生成任务。贪婪搜索和束搜索在生成高质量的、连贯的文本时表现出色,而 Top-K 和核采样在对话生成、故事生成等需要多样性和创造力的任务中更具表现力。欢迎关注我的后续博文,我将分享更多关于人工智能、自然语言处理和计算机视觉的精彩内容。

不想宅的冷同学 1065

智能搜索算法:A*与贪婪搜索比较

摘要:A算法是一种启发式搜索方法,综合了UCS(统一代价搜索)和贪婪搜索的优点。UCS仅考虑初始节点到待扩展节点的路径耗散g(n),而贪婪搜索仅关注待扩展节点到目标节点的期望耗散f(n)。A算法则同时兼顾g(n)和f(n),通过平衡路径实际代价和启发式估计,确保在最优性和效率之间取得平衡,从而高效找到最优解。

m0_60645919的博客 332

MOOC《人工智能:模型与算法》笔记 chapter 2

MOOC《人工智能:模型与算法》笔记

wbupt2021的博客 2110

贪心最佳优先搜索

原理 贪婪最佳优先搜索Greedy Best First Search,是一种启发式搜索算法,我们也可以将它看做广度优先搜索算法的一种改进;算法思想是将节点按距离目标的距离进行排序,然后以这个距离为代价选择待扩展的节点。 1)广度有限搜索算法相当于一个先进先出的队列; 2)深度有限搜索则相当于一个后进先出的栈; 3)贪婪最佳优先搜索则相当于一个根据代价排序的优先级队列。 在没有障碍物的情况下,Greedy Best First Search通常可以找到一个最短路径而且效率比BFS要高,但在有障碍物

JunJun 7737

第五章 搜索技术

文章目录一、状态空间图二、搜索方法 一、状态空间图 (深度优先) 状态空间图不一定总能画出来,只有两个要素:状态、连接 建立状态空间图,需要:1. 定义状态形式 2. 定义状态之间的连接的意义 3. 定义问题的解的形式(状态解、路线解、最优值解等) 实例: 二、搜索方法 1. 盲目/通用搜索 主要指:深度优先搜索、宽度优先搜索 2. 贪心搜索 贪婪搜索策略:总是做出在当前看来最好的选择,或者采用使得当期按步骤获利最大的选择,因此也叫做贪婪算法。 贪婪搜索策略不考虑整体最优,仅求取局部最优

Vicky 983
上一篇: 【GreatSQL优化器-03】查询开销估算
下一篇: GreatSQL 自动开启复制导致同步报错
GreatSQL社区
博客等级 码龄5年 1210粉丝 390原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值