给定输入(算法)匹配的规则

发布于 2024-12-26 05:55:54 字数 933 浏览 2 评论 0 原文

假设我有以下类别(及其可能的值):

animal: any, cat, dog
color: any, white, black, gray
gender: any, male, female
[...]

或者更一般地说...

category: <array of values>

(1) 假设我有一组可配置规则,例如:

when animal is any, color is gray, gender is male, call x
when animal is dog, color is gray, gender is male, call y
when animal is any, color is any, gender is any, call z
[...]

(2) 以及一些输入值。

问:是否有一种算法可以解决根据给定的输入查找匹配规则(优先级给予找到的最具体的规则)的问题?

例1:

input (animal:dog, color:gray, gender:male)

它会调用“y”

例2:

input (color:gray, gender:female)

它会调用“z”

更合适的方法是基于规则构建搜索树(树的每个级别都是一个类别)?

比如:

- any animal
  - any color
    - any gender => z
  - gray
     - male => x
- dog
  - gray
     - male => y

有更好的方法吗?

谢谢!

Let's suppose I have the following categories (with their possible values):

animal: any, cat, dog
color: any, white, black, gray
gender: any, male, female
[...]

or more generally...

category: <array of values>

(1) Let's say I have a set of configurable rules like:

when animal is any, color is gray, gender is male, call x
when animal is dog, color is gray, gender is male, call y
when animal is any, color is any, gender is any, call z
[...]

(2) And some input values.

Q. Is there an algorithm that solves the problem of finding a matching rule (with a priority given to the most specific rule found) according to the input given?

Ex.1:

input (animal:dog, color:gray, gender:male)

it would call "y"

Ex.2:

input (color:gray, gender:female)

it would call "z"

Is the more appropriate way to do it is building a search tree based on the rules (each level of the tree being a category)?

like:

- any animal
  - any color
    - any gender => z
  - gray
     - male => x
- dog
  - gray
     - male => y

Is there a better way of doing it?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

草莓味的萝莉 2025-01-02 05:55:54

我会将规则散列到映射中,然后使用相同的散列进行查找。

map[hash(animal, color, gender)] = function to call

call map[hash(inputanimal, inputcolor, inputgender)]

这将确保更快地创建规则并解析正确的函数以根据输入调用。

如果规则必须完全匹配,否则属于通用的any,any,any,那么只需通过以下方式完成:

if map.contains(hash(inAnimal, inColour, inGender)) 
   x = map[hash(inAnimal, inColour, inGender)]
else
   x = map[hash(any, any, any)]

否则,如果它从输入开始并连续选择每个参数上的any规则,那么您可以这样做。

让哈希函数接受值数组。当您尝试匹配规则时,您从输入开始,然后连续将每个输入切换到任何一个,直到找到匹配项。

def key hash(array[])

....

解决过程...

input[] = {inAnimal, inColour, inGender}
function x
for(i = 0 to input.size) {
   if(map.contains(hash(input)) {
      x = map[hash(input)]
      break
   }
   input[i] = any
}
call x

I would hash the rules into a map and then look up with same hash.

map[hash(animal, color, gender)] = function to call

call map[hash(inputanimal, inputcolor, inputgender)]

This would ensure faster creation of rules and resolution of the correct function to call based on input.

If the rule must be matched exactly or else fall to the generic any,any,any then it is simply done by:

if map.contains(hash(inAnimal, inColour, inGender)) 
   x = map[hash(inAnimal, inColour, inGender)]
else
   x = map[hash(any, any, any)]

Otherwise if it starts with the input and successively selects the any rule on each parameter then you could do this.

Have the hash function accept an array of values. When you try to match a rule, you start with the input, and then successively switch each to any, until you find a match.

def key hash(array[])

....

resolution process...

input[] = {inAnimal, inColour, inGender}
function x
for(i = 0 to input.size) {
   if(map.contains(hash(input)) {
      x = map[hash(input)]
      break
   }
   input[i] = any
}
call x
七色彩虹 2025-01-02 05:55:54

经过以下修改的决策树可以工作:

  1. 使用所有规则以正常方式创建决策树,以“any”作为边
  2. 递归遍历时,遍历“value”和“any”并跟踪数字“any”在每个解决方案中,返回具有最少 'any' 的解决方案

    def 遍历(值、级别、树、任意计数):
    如果树是一片叶子:
    返回(appr_func,anyCount)

    <前><代码>v1 = 无
    如果树中的值[级别]:
    v1 = 遍历(值,级别+1,树[值[级别]]],anyCount)

    v2 = 无
    如果树中有“任何”:
    v2 = 遍历(值,级别+1,树['任意'],任意计数+1)

    如果 v1!=无:
    如果 v2!=无:
    如果 v1[1]

A decision tree with following modifications would work:

  1. Create the decision tree in normal way with 'any' as edges using all the rules
  2. While traversing recursively, traverse to both 'value' and 'any' and keep track of number 'any's in each solution, return the one with minimum 'any's

    def traverse(values, level, tree,anyCount):
    If tree is is a leaf:
    return (appr_func, anyCount)

    v1 = None
    if values[level] in tree:
        v1 = traverse(values, level+1, tree[values[level]]], anyCount)
    
    v2 = None
    if 'any' in tree:
        v2 = traverse(values, level+1, tree['any'], anyCount+1)
    
    if v1!=None:
        if v2!=None:
            if v1[1]<v2[1]:
                return v1
            else:
                return v2
        else:
            return v1
    elif v2!=None:
        return v2
    else:
        return None
    
山人契 2025-01-02 05:55:54

正确的答案取决于您想要获得多奇特的效果。有些东西像 Rete 算法。谷歌“专家系统”。我曾在拥有规则评估系统的大公司工作过,但他们并不是在内部编写这些系统,而是购买商业包。

如果您的需求很简单,那么每个级别都是一个类别的搜索树就可以了。如果应用程序只有特定的项目和一个通用的“任何”项目,那么这将工作得很好。如果存在多个级别的通用性(“哺乳动物”、“脊椎动物”、“动物”),那就会变得更加困难。

如果速度是问题,但内存使用不是问题,那么您也可以尝试哈希表的哈希表方法。哈希表中的每个条目都是一个键值对。在顶级哈希表中,键是顶级类别:“狗”、“猫”、“任何”。该值是另一个哈希表。在第二级哈希表中,键是颜色,值是另一个哈希表。等等。最深哈希表的值包含函数指针、闭包或编程语言提供的任何动态调用方法。

The right answer depends on how fancy you want to get. There are things like the Rete algorithm. Google "expert systems". I've worked in big corporations that have rule evaluation systems, but they don't write them in-house-- they buy a commercial package.

If your needs are simple, then a search tree where each level is a category would work. If the application only has specific items and one general "any" item, this would work fine. If there are multiple levels of generality ("mammal", "vertebrate", "animal") it gets tougher.

If speed is an issue, but memory usage is not, then you could also try the hashtables-of-hashtables approach. Each entry in a hashtable is a key-value pair. In the top-level hashtable, the key is the top category: "dog", "cat", "any". The value is another hashtable. In the second-level hashtable, the key is the color and the value is a another hashtable. And so on. The value of the deepest hashtable contains a function pointer, closure, or whatever method of dynamic invocation your programming languages offers.

一百个冬季 2025-01-02 05:55:54

我首先会给所有变量一个唯一的值(数组位置)

动物:任意 = 0;猫=1;狗 = 2
性别:任意=0;男 = 1;女性 = 2
颜色:任意 = 0;白色=1;黑色=2;灰色=3;

然后我会给每个可能的组合赋予一个查找值。

             Animal-|        ANY        |       cat         |       dog         |       
                    ------------------------------------------------------------- 
             Gender-| any | male |female| any | male |female| any | male |female| 
                    ============================================================= 
      Color-any     |  0  |   1  |   2  |  3  |   4  |   5  |  6  |   7  |   8  |
                    ------------------------------------------------------------- 
            white   |  9  |  10  |  11  | 12  |  13  |  14  | 15  |  16  |  17  |
                    ------------------------------------------------------------- 
            black   | 18  |  19  |  20  | 21  |  22  |  23  | 24  |  25  |  26  |   
                    ------------------------------------------------------------- 
            gray    | 27  |  28  |  29  | 30  |  32  |  33  | 34  |  35  |  36  |
                    =============================================================

每个查找值可以通过以下方式计算:

(Animal * number of animals) + Gender + (Color * number of animals * number of sexes)

或在以下情况下:
动物是任意的,(0)
颜色为灰色,(3)
性别是男,(1)

(Animal * number of animals) + Sex + (Color * number of animals * number of sexes)
(   0   *        3         ) +  1  + (  3   *        3          *        3       )  

(0 * 3) + 1 + (3 * 3 * 3)  
   0    + 1 +      27       = 28 (the lookup value from the grid above)

28 表示呼叫 X。

所以在你的程序中:

计算你的值
将该值与已知情况进行比较

if Value in (1,2,8,13,14,15,21,28)    then X
if value in (3,4,5,23,24,26,34,35,36) then Y
if value in (0,9,12,16,17,22,25)      then Z

显然,这些值实际上可以存储在配置文件中,因此您可以更改逻辑而无需重新编译。

I would first give all variables a unique value (array position)

Animal: any = 0; cat = 1; dog = 2
Gender: any = 0; male = 1; female = 2
Color : any = 0; white = 1; black = 2; gray = 3;

Then I would give each possible combination is given a lookup value.

             Animal-|        ANY        |       cat         |       dog         |       
                    ------------------------------------------------------------- 
             Gender-| any | male |female| any | male |female| any | male |female| 
                    ============================================================= 
      Color-any     |  0  |   1  |   2  |  3  |   4  |   5  |  6  |   7  |   8  |
                    ------------------------------------------------------------- 
            white   |  9  |  10  |  11  | 12  |  13  |  14  | 15  |  16  |  17  |
                    ------------------------------------------------------------- 
            black   | 18  |  19  |  20  | 21  |  22  |  23  | 24  |  25  |  26  |   
                    ------------------------------------------------------------- 
            gray    | 27  |  28  |  29  | 30  |  32  |  33  | 34  |  35  |  36  |
                    =============================================================

Each lookup value can be calculated by the following:

(Animal * number of animals) + Gender + (Color * number of animals * number of sexes)

or in the case of:
animal is any, (0)
color is gray, (3)
gender is male, (1)

(Animal * number of animals) + Sex + (Color * number of animals * number of sexes)
(   0   *        3         ) +  1  + (  3   *        3          *        3       )  

(0 * 3) + 1 + (3 * 3 * 3)  
   0    + 1 +      27       = 28 (the lookup value from the grid above)

28 means call X.

So in your program:

Calculate you value
Compare that value against known cases

if Value in (1,2,8,13,14,15,21,28)    then X
if value in (3,4,5,23,24,26,34,35,36) then Y
if value in (0,9,12,16,17,22,25)      then Z

Obviously those value could actually be stored in a config file so you could change the logic without a re-compile.

滴情不沾 2025-01-02 05:55:54

您几乎可以直接将其转换为 scala 代码。

通常,您会在 scala 中使用大写的 Animal、Cat、Dog,但为了匹配您的示例,我在这里保留了惯例:

abstract sealed class animal () {}
 object cat extends animal () {}
 object dog extends animal {}

abstract sealed class color () {}
 object white extends color {}
 object black extends color {}
 object gray  extends color {}

abstract sealed case class gender () {}
 object male   extends gender {}
 object female extends gender {}

def input (a: Option[animal], c: Option[color], g: Option[gender]) = (a, c, g) match {
  case (Some (dog), Some (gray), Some (male)) => println ("y called without freedom")
  case (_,          Some (gray), Some (male)) => println ("x called with animal" + a)
  case (_,          _,           _          ) => println ("z called with anmimal: " + a + "\tcolor: " + c + "\tgender: " + g)
}

input (Some (dog), Some (gray), Some (male))
input (None,       Some (gray), Some (female))

结果:

y called without freedom
x called with animal: None

您必须注意“输入”方法中的排序。具体方法必须先于非具体方法。

在某些情况下,根据您的描述,无法决定要做什么,但您必须决定先进行哪个测试:

(a, c, _)
(_, c, g)
(a, _, g) 

是否所有人都有 1 个开放案例。如果没有其他内容,(a, c, g) 可以匹配它们中的任何一个,但只会匹配第一个。

您必须提供一般情况(_、_、_),但如果没有意义,可能会引发错误。

You can nearly directly translate this into scala code.

Idiomatically, you would use Animal, Cat, Dog - with uppercase in scala, but to match your example, I leave the road of convention here:

abstract sealed class animal () {}
 object cat extends animal () {}
 object dog extends animal {}

abstract sealed class color () {}
 object white extends color {}
 object black extends color {}
 object gray  extends color {}

abstract sealed case class gender () {}
 object male   extends gender {}
 object female extends gender {}

def input (a: Option[animal], c: Option[color], g: Option[gender]) = (a, c, g) match {
  case (Some (dog), Some (gray), Some (male)) => println ("y called without freedom")
  case (_,          Some (gray), Some (male)) => println ("x called with animal" + a)
  case (_,          _,           _          ) => println ("z called with anmimal: " + a + "\tcolor: " + c + "\tgender: " + g)
}

input (Some (dog), Some (gray), Some (male))
input (None,       Some (gray), Some (female))

Result:

y called without freedom
x called with animal: None

You have to take care on the sorting in the 'input'-Method. Specific methods have to come before unspecific ones.

And there are some cases, where, from your description it is undecideable what to do, but you have to decide, which test comes first:

(a, c, _)
(_, c, g)
(a, _, g) 

do all have 1 open case. If there is nothing else, (a, c, g) could match any of them, but will only match the first one.

You have to provide a general case (_, _, _), but may throw an error, if it doesn't make sense.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文