[rust-021]如何把production加入到规则引擎的网络

Production,产生式规则。

在开源框架,对应的代码如下:

    pub fn add_production(&mut self, production: Production) {
        let log = self.log.new(o!("production_id" => production.id.0));
        trace!(log, "add production"; "production" => ?production);

        if production.conditions.is_empty() {
            error!(log, "production has no conditions");
            return;
        }

        //dummy node是整个网络的root节点。获取dummy node id,以遍历整个网络
        // rete网络参考《Production Matching for Large Learning Systems》第10页。
        let mut current_node_id = self.dummy_node_id;

        //每个产生式规则,if conditions then actoion。
        // 每个产生式规则,有一个或者多个condtion,逐个condition遍历,加入网络
        for i in 0..production.conditions.len() {
            //处理第N个条件
            let condition = production.conditions[i];
            trace!(log, "add condition"; "condition" => ?condition);

            // build or share alpha memory
            // 从condition生成alpha test
            let alpha_test = AlphaTest::from(condition);
            // Returns either an existing id or generates a new one.
            // 如果alpha test的id是已存的,返回id,如果不存在,生成新id,以便创建新alpha memory
            let alpha_memory_id = self
                .alpha_tests
                .get(&alpha_test)
                .cloned()
                .unwrap_or_else(|| AlphaMemoryId(self.id_generator.next()));
            // If we need a new alpha memory, create it.
            // 如果没有alpha memory,创建一个
            if !self.alpha_network.contains_key(&alpha_memory_id) {
                // Collect the WMEs that should already be in this
                // memory.
                // 创造一个alpha memory,需要将符合这个alpha test的wme找出来,存储到alpha memory
                let wmes = self
                    .wme_alpha_memories
                    .iter_mut()
                    .filter(|(wme, _)| alpha_test.matches(wme))
                    .map(|(wme, alpha_memories)| {
                        // Keep track of which alpha memories contain
                        // this WME.
                        alpha_memories.push(alpha_memory_id);
                        *wme
                    })
                    .collect();

                // 创建 alpha memory
                let memory = AlphaMemory {
                    id: alpha_memory_id,
                    wmes,
                    successors: vec![],
                    test: alpha_test,
                };
                trace!(log, "created alpha memory";
                    "test" => %alpha_test,
                    "id" => ?memory.id,
                    "wmes" => memory.wmes.len());

                // 把alpha test添加到alpha_tests,做记录
                self.alpha_tests.insert(alpha_test, memory.id);
                // 把alpha memroy添加到 alpha network网络
                self.alpha_network.insert(memory.id, memory);

                observe!(
                    log,
                    Trace::AddedAlphaMemory {
                        id: alpha_memory_id.0,
                        test: trace::AlphaMemoryTest {
                            id: alpha_test.0[0],
                            attribute: alpha_test.0[1],
                            value: alpha_test.0[2],
                        }
                    }
                );
            }
            //获取 alpha memory,以备后续操作
            let alpha_memory = &self.alpha_network[&alpha_memory_id];

            // get join tests from condition
            // NOTE: This does not handle intra-condition tests.
            // todo 这一步比较复杂难解要再考虑考虑
            let tests: Vec = condition
                .variables() //把condition里的varialbe拿出来处理,一个condition最多有3个variable,最少0个,返回序号和Option值
                .filter_map(|(alpha_field, variable_id)| {//注意上一步Item = (usize, VariableID)
                    production.conditions[0..i]//当前是第i个conditon,取从0到第i-1个condition做处理
                        .iter()//获取iterator遍历这i个
                        .rev()// rev之后,反转,也就是说,第0个变成最后一个,第i-1个变成第0个
                        .enumerate()//枚举出来,有序号。实际上需要就变成了distance,下一步用的到
                        .find_map(|(distance, prev_condition)| {
                            prev_condition
                                .variables()
                                .find(|(_, var)| *var == variable_id)
                                .map(|(i, _)| (i, distance))
                        })
                        .map(|(beta_field, beta_condition_offset)| JoinNodeTest {
                            alpha_field,
                            beta_field,
                            beta_condition_offset,
                        })
                })
                .collect();

            // build or share join node
            current_node_id = self
                .beta_network
                .neighbors(current_node_id)
                .find(|id| match self.beta_network[*id] {
                    ReteNode::Join {
                        alpha_memory: join_amem,
                        tests: ref join_tests,
                    } if join_amem == alpha_memory.id && *join_tests == tests => true,
                    _ => false,
                })
                .unwrap_or_else(|| {
                    // If we couldn't find a node to share, create
                    // one.
                    let new_node = ReteNode::Join {
                        alpha_memory: alpha_memory_id,
                        tests,
                    };
                    let id = self.beta_network.add_node(new_node);
                    self.beta_network.add_edge(current_node_id, id, ());
                    trace!(log, "create join node"; "id" => ?id);

                    observe!(
                        log,
                        Trace::AddedNode {
                            id: id.index(),
                            parent_id: current_node_id.index(),
                            kind: trace::NodeKind::Join,
                            children: vec![],
                            alpha_node_id: Some(alpha_memory_id.0),
                        }
                    );

                    // link to alpha memory
                    self.alpha_network
                        .get_mut(&alpha_memory_id)
                        .unwrap()
                        .successors
                        .push(id);
                    id
                });

            // build or share beta memory
            // 有id,返回id,没有id,创建一个beta节点,返回新id
            current_node_id = if i + 1 < production.conditions.len() {
                self.beta_network
                    .neighbors(current_node_id)
                    .find(|id| match self.beta_network[*id] {
                        ReteNode::Beta { .. } => true,
                        _ => false,
                    })
                    .unwrap_or_else(|| {
                        // If we couldn't find a node to share, create
                        // one.
                        let new_node = ReteNode::Beta { tokens: vec![] };
                        let id = self.beta_network.add_node(new_node);
                        self.beta_network.add_edge(current_node_id, id, ());
                        trace!(log, "create beta memory"; "id" => ?id);

                        observe!(
                            log,
                            Trace::AddedNode {
                                id: id.index(),
                                parent_id: current_node_id.index(),
                                kind: trace::NodeKind::Beta,
                                children: vec![],
                                alpha_node_id: None,
                            }
                        );

                        self.activate_new_node(log.clone(), current_node_id, id);

                        id
                    })
            } else {
                current_node_id
            };
        }

        // Build new production node
        // 创建p节点,p节点也就是 产生式规则 节点,一个节点对应一条规则
        let new_node = ReteNode::P {
            production: production.id,
            activations: vec![],
        };
        let id = self.beta_network.add_node(new_node);
        trace!(log, "create p node"; "id" => ?id);
        self.beta_network.add_edge(current_node_id, id, ());
        self.productions.insert(production.id, id);
        trace!(log, "new p node"; "id" => ?id);

        observe!(
            log,
            Trace::AddedNode {
                id: id.index(),
                parent_id: current_node_id.index(),
                kind: trace::NodeKind::P,
                children: vec![],
                alpha_node_id: None,
            }
        );

        observe!(
            log,
            Trace::AddedProduction {
                id: production.id.0,
                p_node_id: id.index(),
            }
        );

        // 激活节点
        if current_node_id != self.dummy_node_id {
            self.activate_new_node(log.clone(), current_node_id, id);
        }
    }

这块代码比较复杂,先做一些注释,也比较难以测试。后续再继续分析。

你可能感兴趣的:(rust,rust)