调研规则引擎用于八字命理

熟悉命理书的朋友都知道,书上计划都是一些条文组成的断语,从下表可以看到,命理大师们习惯描述什么条件,会出现什么样的情况,这样看起来是不是很像规则引擎的职能呢?于是我就想调研一下java相关的规则引擎,是否满足命理的灵活多变的需要。或许比搞些设计模式,纯手工编码要好维护得多吧.
1
先不着急自己搭建环境,先了解有哪些,他们是什么,他们能干什么,在哪些领域有所应用。
1 drool
Drools中文网,DROOLS(JBOSS RULES )具有一个易于访问企业策略、易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快、效率高。业务分析师或审核人员可以利用它轻松查看业务规则,从而检验是否已编码的规则执行了所需的业务规则。
1.1 规则引擎
从上面官网给出的定义,首先看看什么业务规则引擎。参考业务规则引擎,业务规则包括了条件和触发操作两部分内容。而引擎是事物内部的重要的运行机制,规则引擎即重点是解决规则如何描述,如何执行,如何监控等一系列问题。它这个定义描述的比较清楚
再看业务规则和规则引擎这篇文章,我们知道如何更好地构建规则,它包含的要素如下:

  • 事实:对业务的真实描述

  • 约束:满足什么条件才可以执行

  • 动作触发规则:触发的动作是什么

  • 推论:如果怎样,结果怎样

  • 计算:业务计算
    那么通过什么工具,来描述业务规则呢?

  • 决策表:以表格形式描述业务规则,一行一天规则,列表示条件,当条件满足,触发动作。这个跟我上面的图一样

  • 决策树:将一组业务规则通过树形结构表示,每一个分支表示一条决策路径,描述推论的规程,叶子节点即结果或动作

  • 规则语言:通过计算机语言描述规则

  • 脚本:描述过程的业务逻辑,if——then——else。
    1.2 开源的有哪些
    查看oschina,开源的业务规则引擎真心不少。

  • aswan:陌陌开发的风控系统静态规则引擎,用python写的,momosecurity/aswan
    ,当然github上也有人用java重写,根据Aswan轻量级风控静态规则引擎 | WitAwards2019“年度开源项目”参评巡礼中描述,aswan的规则引擎是面向用户行为的分析,预置了名单型策略(黑白名单)、布尔型策略(用户的属性阈值控制)、时段频率控制型策略、限制用户数型策略,这个项目对我们命理规则帮助不大。

  • stepchain:没什么名气,一年也没有更新,忽略

  • RuleEngine:

  • URule:以 RETE 算法为基础,提供了商业PRO版本和开源版,这种情况就不考虑了。应该有坑。就跟mongo一样,频繁读写副本集模式就容易挂掉,还不知是什么原因。

  • Easy Rules:基于POJO的开发与注解的编程模型,有点意思,可以深入分析一下。

  • Aristotle:Ruby 语言开发,不看

  • JBoss BPM Suite:业务流程管理平台,跟我的需求不符。

  • JBoss BRMS:JBoss BRMS是用于业务规则管理和复杂事件处理的平台,对我来说太重了。映象中JBPM之前都是用来做OA工作流程的

  • JBoss OptaPlanner:OptaPlanner 是轻量级的,可嵌入的规划引擎

  • Tohu:资料太少,没有调查性

  • A2D:基于C#等,不看

  • Esper:Complex Event Processing,目的是让用户能够通过它提供的接口,构建一个用于处理复杂事件的应用程序。跟我的场景不匹配。

  • NRuleEngine:c#规则引擎,我是java、python系,这个不用看

  • Simple Rule Engine:基于 .NET 开发,这个也不用看

  • Hammurabi:Scala编写的,暂不看

  • OpenL Tablets:penl Tables 是一个开源的规则引擎,大部分规则都可以通过Excel编写,这个有点意思,规则引擎–Openl Tables快速入门,这个里面描述通过提供API访问业务规则,看起来还不错。

  • Interleave:基于 Web 的业务流程自动化应用,对我用不着。

  • Activiti:工作流,用于OA,对我用不着。

  • Intalio BPM:工作流,不适用我的场景

  • Prova:它的设计工作在分布式企业服务总线和OSGi环境,有些重,不看了。

  • JRuleEngine:网上有些跟Drools的材料,规则引擎 Drools与JRuleEngine,drools提供了JRuleEngine的一些额外的内容。

  • InfoSapient:没看到太多的介绍,不看

  • JEOPS:sourceforge最后更新是2015年,也没人下载,pass。

  • Mandarax:Mandarax规则引擎调研.ppt中描述不支持API JSR-94,采用的是基于反向推理,即归纳法,那也没什么可看的了。

  • JRules:被IBM收购,WebSphere ILOG JRules 规则引擎运行模式简介。功能很强大,还有个 Rule Studio 设计。

  • JLisa:sourceforge last update为2013年,不看

  • NxBRE:.NET平台,不看

  • OpenRules:规则知识库是Excel(Decision Tables)方式的,不支持把知识库放在数据库中。有点意思。

  • Drools Expert:Drools Expert 是 Drools 平台上的一个规则引擎

  • Jess:体积小,重量轻,并且是最快的规则引擎之一,Ilog、Drools、Jess规则引擎的Rule Language 对比,看看里面编写规则,实在不想细看,对我们的编码习惯差异太大,果断放弃。

  • Drools.NET :.NET 版的 Drools,不看

  • Drools:名气很大

  • Apache Camel :物联网中也要用到,可以深入

1.3 LHS和RHS
阅读Gitee 极速下载 / RuleEngine,提到了RuleEngine可以直接使用SQL语句来定义规则的LHS部分,也可以自定义执行体部分(RHS)。那么什么是LHS和RHS呢?阅读LHS和RHS理解快速理解JavaScript 中的 LHS 和 RHS 查询,赋值操作的左边和右边,编译原理中有些用,一般我们用不着。

1.4 RETE算法
RETE算法简述 & 实践,Rete 是一种进行大量模式集合和大量对象集合间比较的高效方法,通过网络筛选的方法找出所有匹配各个模式的对象和规则,当初考研的时候自学过编译原理,刚开始看懂了,不过2个月就全忘了,这玩意太复杂,研究不过来,了解干什么就行了。

1.5 JSR-94规则
参见JAVA规则引擎JSR-94笔札Java 规则引擎与其 API (JSR-94)
过去大部分的规则引擎开发并没有规范化,有其自有的 API,这使得其与外部程序交互集成不够灵活。转而使用另外一种产品时往往意味需要重写应用程序逻辑和 API 调用,代价较大。规则引擎工业中标准的缺乏成为令人关注的重要方面。2003 年 11 月定稿并于 2004 年 8 月最终发布的 JSR 94(Java 规则引擎 API)使得 Java 规则引擎的实现得以标准化。从这段描述就知道 JSR 94的意义了。
1.6 DSL
Domain Specified Language,领域专用语言
1.7 kie
Knowledge Is EveryThing,参见Drools从入门到精通之KIE
1.8 springboot整合
首先看pom.xml,参考了半小时搞定,规则引擎Drools 集成 springboot 热加载

<version.drools>7.47.0.Final</version.drools>

<dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-core</artifactId>
            <version>${version.drools}</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-compiler</artifactId>
            <version>${version.drools}</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-decisiontables</artifactId>
            <version>${version.drools}</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-templates</artifactId>
            <version>${version.drools}</version>
        </dependency>
        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-api</artifactId>
            <version>${version.drools}</version>
        </dependency>
        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-spring</artifactId>
            <version>${version.drools}</version>
        </dependency>

2 Easy Rules
easy-rules-core,2020年5月还有更新。查看规则引擎 Easy Rules 使用实例(一),在easy Rules中规则提供了java和yml两种方式,将if else更加优雅的表达。不过看了他的示例代码,你可能觉得 增加了扩展性,也增加了编写复杂度。再看规则引擎 Easy Rules 使用实例(二中的建议初学者将业务逻辑写在java中,一类规则,当中可能就有很多的内部类。
使用easy rules的优先级不是可视化的,逻辑不是很直观。
另外针对八字命理,规则太多了,那是不是我要定义很多的规则类呢?而每个规则断语很多都是只有符合一些条件,才能怎样,没有说不符合,又会怎样。
参见Java规则引擎 Easy Rules
将我之前的代码调整为easy rules的模式,虽然我之前是在过滤器模式来做的,调整后感觉确实优雅多了,而且逻辑也非常清晰。

@Override
    public void doFilter(BaZi bazi, List<QiangRuoAssertionDto> assertions, QiangRuoFilterChain chain) {
        QiangRuoAssertionDto assertionDto = null;
        if (WuXingUtil.isYinBi(bazi.getDayDiZhi().getWuXing(), bazi.getDayTianGan().getWuXing()) && bazi.getHourDiZhi()!=null
                && WuXingUtil.isYinBi(bazi.getHourDiZhi().getWuXing(), bazi.getDayTianGan().getWuXing())
            && !WuXingUtil.isYinBi(bazi.getYearDiZhi().getWuXing(), bazi.getDayTianGan().getWuXing())
                && !WuXingUtil.isYinBi(bazi.getMonthDiZhi().getWuXing(), bazi.getDayTianGan().getWuXing())){
            if (bazi.getDayDiZhi().getWuXing() == bazi.getHourDiZhi().getWuXing()
                    && WuXingUtil.isYin(bazi.getDayDiZhi().getWuXing(), bazi.getDayTianGan().getWuXing())){
                // 日时双印
                assertionDto = new QiangRuoAssertionDto();
                assertionDto.setAssertion("日时双印,年月非根印,不论组合,不看天干,皆身弱论命");
                assertionDto.setSection(SectionEnum.QIANG_RUO);
                assertionDto.setQiangruo(QiangRuoEnum.RUO);
                assertions.add(assertionDto);
            } else{
                if (TianGanUtil.yinBiYiPian(bazi) || TianGanUtil.ganTou(bazi.getDayGan().getZhengYin(),bazi)+TianGanUtil.ganTou(bazi.getDayGan().getBiJian().getWuXing(),bazi)>=2){
                    assertionDto = new QiangRuoAssertionDto();
                    assertionDto.setAssertion("根根、印根、根印在日时同时出现,天干印比一片,皆以旺论");
                    assertionDto.setSection(SectionEnum.QIANG_RUO);
                    assertionDto.setQiangruo(QiangRuoEnum.WANG);
                    assertions.add(assertionDto);
                } else{
                    assertionDto = new QiangRuoAssertionDto();
                    assertionDto.setAssertion("根根、印根、根印在日时同时出现,年月时干有一处不是印比,以弱论,合化出的印比不能算!");
                    assertionDto.setSection(SectionEnum.QIANG_RUO);
                    assertionDto.setQiangruo(QiangRuoEnum.RUO);
                    assertions.add(assertionDto);
                }
            }
        }
        chain.doFilter(bazi, assertions, chain);
    }

先看看pom.xml中的配置

<version.easyrule>4.0.0</version.easyrule>
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-core</artifactId>
    <version>${version.easyrule}</version>
</dependency>
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-support</artifactId>
    <version>${version.easyrule}</version>
</dependency>
<dependency>
    <groupId>org.jeasy</groupId>
    <artifactId>easy-rules-mvel</artifactId>
    <version>${version.easyrule}</version>
</dependency>

接着是定义yml

# 生 1 克 2 助 3 泄 4 耗 5
# 印 1 官 2 比劫根 3 食伤 4 财 5
# 年月时天干印比一片 1,天干合化印比一片 2,有一处不是印比 0
---
name: "日时根印规则1"
description: "日时双印,年月非根印,不论组合,不看天干,皆身弱论命"
priority: 1
condition: "feature.yz!=1 && feature.yz!=3 && feature.mz!=1 && feature.mz!=3 && feature.dz==1 && feature.hz==1"
actions:
  - "feature.setResult(\"弱\");"
---
name: "日时根印规则2"
description: "根根、印根、根印在日时同时出现,天干印比一片,皆以旺论"
priority: 2
condition: "feature.yz!=1 && feature.yz!=3 && feature.mz!=1 && feature.mz!=3 && ((feature.dz==1 && feature.hz==3) || (feature.dz==3 && feature.hz==3) ||(feature.dz==3 && feature.hz==1)) && feature.ymhg==1"
actions:
  - "feature.setResult(\"旺\");"
---
name: "日时根印规则3"
description: "根根、印根、根印在日时同时出现,年月时干有一处不是印比,以弱论,合化出的印比不能算!"
priority: 3
condition: "feature.yz!=1 && feature.yz!=3 && feature.mz!=1 && feature.mz!=3 && ((feature.dz==1 && feature.hz==3) || (feature.dz==3 && feature.hz==3) || (feature.dz==3 && feature.hz==1)) && feature.ymhg==0"
actions:
  - "feature.setResult(\"弱\");"

easy-rules mvel yaml 格式规则配置&&试用二——rule 数据返回结果,从这篇文章中我知道了我们需要定义一个顶级的规则,才好拿到easy rules的返回值,也算是一种折中的办法,不过没有成功。Easy Rules core包 规则引擎这篇文章讲的比较细致。不过到返回值的时候,感觉哪些示例都是在过家家,我要哪些system.out.print有啥用呢?
第一个对象,用于传值和接受返回值

package com.dzmsoft.bazi.dto;

public class BaziFeatureDto {

    private Integer yz;
    private Integer mz;
    private Integer dz;
    private Integer hz;
    private Integer ymhg;
    private String result;

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }



    public Integer getYz() {
        return yz;
    }

    public void setYz(Integer yz) {
        this.yz = yz;
    }

    public Integer getMz() {
        return mz;
    }

    public void setMz(Integer mz) {
        this.mz = mz;
    }

    public Integer getDz() {
        return dz;
    }

    public void setDz(Integer dz) {
        this.dz = dz;
    }

    public Integer getHz() {
        return hz;
    }

    public void setHz(Integer hz) {
        this.hz = hz;
    }

    public Integer getYmhg() {
        return ymhg;
    }

    public void setYmhg(Integer ymhg) {
        this.ymhg = ymhg;
    }


}

然后是调用的测试验证,skipOnFirstFailedRule这个并不是什么的时候都可以设置的

package com.dzmsoft.bazi.rule.qiangruo.shy;

import com.dzmsoft.bazi.dto.BaziFeatureDto;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.api.RulesEngineParameters;
import org.jeasy.rules.core.DefaultRulesEngine;
import org.jeasy.rules.mvel.MVELRuleFactory;
import org.jeasy.rules.support.reader.YamlRuleDefinitionReader;

import java.io.FileReader;

public class Test {

    public static void main(String[] args) throws Exception {
        RulesEngineParameters parameters = new RulesEngineParameters()
                .skipOnFirstAppliedRule(true)
//                .skipOnFirstFailedRule(true)
//                .skipOnFirstNonTriggeredRule(true)
                ;
        RulesEngine rulesEngine = new DefaultRulesEngine(parameters);

        MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());
        String fileName = Test.class.getClassLoader().getResource("shy32.yml").getFile();
        System.out.println(fileName);
        Rules rules = ruleFactory.createRules(new FileReader(fileName));
        BaziFeatureDto baziFeatureDto = new BaziFeatureDto();
        baziFeatureDto.setYz(2);
        baziFeatureDto.setMz(2);
        baziFeatureDto.setDz(1);
        baziFeatureDto.setHz(3);
        baziFeatureDto.setYmhg(0);
        Facts facts = new Facts();
        facts.put("feature",baziFeatureDto);
        rulesEngine.fire(rules,facts);
        System.out.println(baziFeatureDto.getResult());

    }
}

3 OptaPlanner
OptaPlanner逐步学习(0) : 基本概念 - OptaPlanner,规划问题, 约束,方案,OptaPlanner是一个对待规划的方案组合进行优化的引擎。规划问题是 - 基于有限资源,及指定约束条件下达到优化目标(包括资源、排程安排等优化)。比如最大化利润、最小化影响,有点像运筹学里面的内容。现阶段没有这方面的要求,这哪是搁置。不过感觉这个应该蛮有用。
4 Apache Camel
Apache Camel系列(1)----使用场景,从这篇文章可以知Apache Camel是一个基于Enterprise Integration Pattern(企业整合模式,简称EIP)的开源框架,可以解决不同的应用系统之间以不同的方式传递消息
4.1 Akka
为什么Akka(Actor模型)在中国不温不火?
,但Flink通过Akka实现的分布式通信。
4.2 Actor模型
十分钟理解Actor模式,MapReduce就是一种典型的Actor模式,Actor模型share nothing,与共享内存型相反,共享内存更适合单机多核的并发编程。而单机多核并发编程就需要注意锁和内存原子性等一系列线程问题,看起来了Actor模式更简单。
4.3 EIP
Enterprise Integration Patterns 企业集成模式(EIP),什么时候使用Apache camel

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

warrah

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值