C# 如何在C语言中实现交互式决策树#

C# 如何在C语言中实现交互式决策树#,c#,machine-learning,artificial-intelligence,chatbot,decision-tree,C#,Machine Learning,Artificial Intelligence,Chatbot,Decision Tree,我需要允许用户通过在屏幕上显示的两个简单选项之间进行选择来选择他们自己的路径,以便进入下一组选项,直到他们到达其中一个结尾,即应该实现以下目标: 我尝试了以下代码,但每次只计算左侧代码。我想知道我如何才能达到像上图(覆盖所有分支)这样的效果?例如,如果用户选择“否”,则应用程序不应该向用户询问任何进一步的问题,而只是简单地显示“也许你想要一个比萨饼”消息。我已经用决策树算法完成了这项工作,并且需要修复它,这样它就可以像上图一样覆盖左右两侧 namespace ConsoleApp3 {

我需要允许用户通过在屏幕上显示的两个简单选项之间进行选择来选择他们自己的路径,以便进入下一组选项,直到他们到达其中一个结尾,即应该实现以下目标:

我尝试了以下代码,但每次只计算左侧代码。我想知道我如何才能达到像上图(覆盖所有分支)这样的效果?例如,如果用户选择“否”,则应用程序不应该向用户询问任何进一步的问题,而只是简单地显示“也许你想要一个比萨饼”消息。我已经用决策树算法完成了这项工作,并且需要修复它,这样它就可以像上图一样覆盖左右两侧

namespace ConsoleApp3
{
    class Program
    {
        static void Main(string[] args)
        {
            var decisionTree = MainDecisionTree();

            var client = new Client();

            Console.WriteLine("Do you want a book? true/false");
            client.Answer[0] = bool.Parse(Console.ReadLine());
            Console.WriteLine("Do you like it? true/false");
            client.Answer[1] = bool.Parse(Console.ReadLine());
            Console.WriteLine("Are you sure? true/false");
            client.Answer[2] = bool.Parse(Console.ReadLine());

            decisionTree.Evaluate(client);

            Console.WriteLine("Press any key...");
            Console.ReadKey();
        }

        private static DecisionQuery MainDecisionTree()
        {
            //Decision 2
            var wantBranch = new DecisionQuery
            {
                Title = "Do you want a book?",
                Test = (client) => client.Answer[0],
                Positive = new DecisionResult { Result = true },
                Negative = new DecisionResult { Result = false }
            };

            //Decision 1
            var deserveBranch = new DecisionQuery
            {
                Title = "Do you like it?",
                Test = (client) => client.Answer[1],
                Positive = wantBranch,
                Negative = new DecisionResult { Result = false }
            };


            //Decision 0
            var sureBranch = new DecisionQuery
            {
                Title = "Are you sure?",
                Test = (client) => client.Answer[2],
                Positive = deserveBranch,
                Negative = new DecisionResult { Result = false }
            };

            return sureBranch;
        }
    }

    public class DecisionResult : Decision
    {
        public bool Result { get; set; }

        public override void Evaluate(Client client)
        {
            Console.WriteLine("\r\nThe result: {0}", Result ? "Buy it" : "You need to wait");
        }
    }

    public class DecisionQuery : Decision
    {
        public string Title { get; set; }
        public Decision Positive { get; set; }
        public Decision Negative { get; set; }
        public Func<Client, bool> Test { get; set; }

        public override void Evaluate(Client client)
        {
            bool result = this.Test(client);
            string resultAsString = result ? "yes" : "no";

            Console.WriteLine($"\t- {this.Title}? {resultAsString}");

            if (result) this.Positive.Evaluate(client);
            else this.Negative.Evaluate(client);
        }
    }

    public abstract class Decision
    {
        public abstract void Evaluate(Client client);
    }

    public class Client
    {
        public bool[] Answer { get; set; } = new bool[3];
    }
}
名称空间控制台ap3
{
班级计划
{
静态void Main(字符串[]参数)
{
var decisionTree=maindcisiontree();
var client=new client();
Console.WriteLine(“你想要一本书吗?对/错”);
client.Answer[0]=bool.Parse(Console.ReadLine());
Console.WriteLine(“你喜欢吗?对/错”);
client.Answer[1]=bool.Parse(Console.ReadLine());
Console.WriteLine(“你确定吗?对/错”);
client.Answer[2]=bool.Parse(Console.ReadLine());
决策树。评估(客户);
Console.WriteLine(“按任意键…”);
Console.ReadKey();
}
私有静态决策查询MainDecisionTree()
{
//决定2
var wantBranch=新决策查询
{
Title=“你想要一本书吗?”,
测试=(客户端)=>client.Answer[0],
正=新决策结果{Result=true},
否定=新决策结果{Result=false}
};
//决定1
var deservbranch=新决策查询
{
Title=“你喜欢吗?”,
测试=(客户端)=>client.Answer[1],
正=wantBranch,
否定=新决策结果{Result=false}
};
//决定0
var sureBranch=新决策查询
{
Title=“你确定吗?”,
Test=(client)=>client.Answer[2],
正=正分支,
否定=新决策结果{Result=false}
};
返回分支机构;
}
}
公共类决策结果:决策
{
公共布尔结果{get;set;}
公共覆盖无效评估(客户端)
{
WriteLine(“\r\n结果:{0}”,结果?“购买”:“您需要等待”);
}
}
公共类决策查询:决策
{
公共字符串标题{get;set;}
公共决策正{get;set;}
公共决策负{get;set;}
公共函数测试{get;set;}
公共覆盖无效评估(客户端)
{
bool结果=本次测试(客户端);
string resultAsString=结果?“是”:“否”;
Console.WriteLine($“\t-{this.Title}?{resultAsString}”);
如果(结果)为阳性,则评估(客户);
否则。否定。评估(客户);
}
}
公共抽象类决策
{
公开摘要无效评估(客户);
}
公共类客户端
{
公共bool[]应答{get;set;}=newbool[3];
}
}

您的决策树设计非常好,只是您询问用户的方式不好。 您可以提前问所有问题,然后再转到决策树。 当然,树不能让被问的问题不被问。 这不是一个决策树问题

您必须将以下几行放在一起:

    Console.WriteLine("Are you sure? true/false");
    client.Answer[2] = bool.Parse(Console.ReadLine());
或者您执行回调或任何架构设计来将逻辑与用户界面分离。 决策树必须问,或者至少知道这个问题。 答案不需要存储,您可以在输入后立即对其进行评估

也许您传递了一些信息,要求用户使用evaluate方法

public interface IAsk
{
    bool Question(string message);
}
对于您的示例,您可以用

public class ConsoleAsk : IAsk
{
    bool Question(string message)
    {
         Console.WriteLine(message);
         return  bool.Parse(Console.ReadLine());
    }
}
您可以这样修改您的评估:

    public override void Evaluate(IAsk ask)
    {
        bool result = ask.Question("do you feel good or bad");
        string resultAsString = result ? "yes" : "no";

        Console.WriteLine($"\t- {this.Title}? {resultAsString}");

        if (result) this.Positive.Evaluate(ask);
        else this.Negative.Evaluate(ask);
    }

当然,您可以将问题替换为您的title属性。

如果我理解您的问题,以下是您的代码更正

我重新命名了一些东西

我调用了
MakeDecisionTree
方法,该方法使用条件树初始化专家系统,并返回根条件

每个
条件
都包含一个
语句
评估
,它可以是
查询
结果

对于
结果
评估
显示
句子

对于
查询
评估
方法要求用户通过
回答问题。使用这个答案,它调用下一个子项的相应的
evaluate

对不起,我的英语在这里,它不是我的母语,我不参与人工智能

static private void DecisionTreeTest()
{
  Console.WriteLine("Please, answer a few questions with yes or no.");
  Console.WriteLine();
  MakeDecisionTree().Evaluate();
}

机器学习?@OlivierRogier不确定它是否相同。我只需要一个最简单的决策树。是的,它是:@OlivierRogier所以你知道我的问题吗?它可以很容易地重新生成。您编写的代码并没有实现所有分支,问题可能会在过程中提出,而不是在评估之前。我没有参与机器学习和决策树,但乍一看,您的算法在
MainDecisionTree
中有缺陷。我添加了一些,不确定您阅读的是哪个状态。请再读一遍。decisionTree.Evaluate(新的控制台ask());并删除所有“客户”行。我如何更改
DecisionResult
类的
Evaluate
方法,因为现在当我选择
nostatic private bool GetUserAnswer(string question)
{
  Console.WriteLine(question);
  string userInput;
  while ( true )
  {
    userInput = Console.ReadLine().ToLower();
    if ( userInput == "yes" )
      return true;
    else
    if ( userInput == "no" )
      return false;
    else
      Console.WriteLine("Your answer is not supported, retry please." +
                        Environment.NewLine + Environment.NewLine +
                        question);
  }
}
static private DecisionTreeQuery MakeDecisionTree()
{
  var queryAreYouSure
    = new DecisionTreeQuery("Are you sure?",
                            new DecisionTreeResult("Buy it."),
                            new DecisionTreeResult("You need to wait."),
                            GetUserAnswer);
  var queryIsItAGoodBook
    = new DecisionTreeQuery("Is it a good book?",
                            new DecisionTreeResult("What are you waiting for? Just buy it."),
                            new DecisionTreeResult("Find another one."),
                            GetUserAnswer);
  var queryDoYouLikeIt
    = new DecisionTreeQuery("Do you like it?",
                            queryAreYouSure,
                            queryIsItAGoodBook,
                            GetUserAnswer);
  var queryDoYouWantABook
    = new DecisionTreeQuery("Do you want a book?",
                            queryDoYouLikeIt,
                            new DecisionTreeResult("Maybe you want a pizza."),
                            GetUserAnswer);
  return queryDoYouWantABook;
}
abstract public class DecisionTreeCondition
{
  protected string Sentence { get; private set; }
  abstract public void Evaluate();
  public DecisionTreeCondition(string sentence)
  {
    Sentence = sentence;
  }
}
public class DecisionTreeQuery : DecisionTreeCondition
{
  private DecisionTreeCondition Positive;
  private DecisionTreeCondition Negative;
  private Func<string, bool> UserAnswerProvider;
  public override void Evaluate()
  {
    if ( UserAnswerProvider(Sentence) )
      Positive.Evaluate();
    else
      Negative.Evaluate();
  }
  public DecisionTreeQuery(string sentence,
                           DecisionTreeCondition positive,
                           DecisionTreeCondition negative,
                           Func<string, bool> userAnswerProvider)
    : base(sentence)
  {
    Positive = positive;
    Negative = negative;
    UserAnswerProvider = userAnswerProvider;
  }
}
public class DecisionTreeResult : DecisionTreeCondition
{
  public override void Evaluate()
  {
    Console.WriteLine(Sentence);
  }
  public DecisionTreeResult(string sentence)
    : base(sentence)
  {
  }
}