这是之前我写的原始的 VB.NET 版本:

http://www.cnblogs.com/RChen/archive/2010/05/17/1737587.html

转化为 C# 版本后,还进行了一些重构。包括修改成了强类型,以及使用了 Parallel.ForEach,但是发现没有收到预期的效果。性能提升比较少。

研究后发现,其实问题的关键在于要通过某种方式对遍历的可能性进行剪枝,这样才能减少遍历次数,从而提升性能。而且,由于结果是通过 yield return 和 IEnumerable 实现的,并没有实现 IList 或者 Array. 所以它本质上并不支持按索引范围拆分的 Parallel.ForEach 工作方式,而实际估计是使用的几个 chunk 轮番读取的低效方式,这样在各个 chunk 之间就有线程同步的开销,如前文所说。这个性能优化只好留待后面有空再继续研究。

下面是目前的状况的实现代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
  
namespace NonDeterministicEngineCS
    class Program
    
        static void Main(string[] args)
        
            Benchmarking(new Action(Test1), "Test1() 执行完成,花费:{0}毫秒。");
            Console.WriteLine("====================================================");
            Benchmarking(new Action(Test2), "Test2() 执行完成,花费:{0}毫秒。");
            Console.WriteLine("====================================================");
            Benchmarking(new Action(Test3), "Test3() 执行完成,花费:{0}毫秒。");
            Console.ReadLine();
        
  
        // 一个简单的测试例子
        public static void Test1()
        
            NonDeterministicEngine engine = new NonDeterministicEngine();
  
            engine.AddParam("a"new int[] { 1, 2, 3, 4, 5, 6 });
            engine.AddParam("b"new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
  
            engine.AddRequire((int a) => a > 2 && a < 9);
            engine.AddRequire((int b) => b > 5 && b <= 10);
            engine.AddRequire((int a, int b) => a == b - 1);
  
            engine.EachResult(
                result => Console.WriteLine("a = {0}, b = {1}", result["a"], result["b"]));
        
  
        // 爱因斯坦谜题
        public static void Test2()
        
            NonDeterministicEngine engine = new NonDeterministicEngine();
  
            engine.AddParam("baker"new int[] { 1, 2, 3, 4, 5 });
            engine.AddParam("cooper"new int[] { 1, 2, 3, 4, 5 });
            engine.AddParam("fletcher"new int[] { 1, 2, 3, 4, 5 });
            engine.AddParam("miller"new int[] { 1, 2, 3, 4, 5 });
            engine.AddParam("smith"new int[] { 1, 2, 3, 4, 5 });
  
            engine.AddRequire((int baker) => baker != 5);
            engine.AddRequire((int cooper) => cooper != 1);
            engine.AddRequire((int fletcher) => fletcher != 1 && fletcher != 5);
            engine.AddRequire((int miller, int cooper) => miller > cooper);
            engine.AddRequire((int smith, int fletcher) =>
                smith != fletcher + 1
                && smith != fletcher - 1);
  
            engine.AddRequire((int fletcher, int cooper) => fletcher != cooper + 1
                && fletcher != cooper - 1);
  
            engine.AddRequire((int baker, int cooper, int fletcher, int miller, int smith) =>
                baker != cooper && baker != fletcher && baker != miller
                && baker != smith && cooper != fletcher && cooper != miller
                && cooper != smith && fletcher != miller && fletcher != smith && miller != smith);
  
            engine.EachResult(
             result =>
                 Console.WriteLine("baker: {0}, cooper: {1}, fletcher: {2}, miller: {3}, smith: {4}"
                         result["baker"],
                         result["cooper"],
                         result["fletcher"],
                         result["miller"],
                         result["smith"])
            );
        
  
        // 八皇后问题的解法
        public static void Test3()
        
            var engine = new NonDeterministicEngine();
  
            engine.AddParam("a"new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
            engine.AddParam("b"new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
            engine.AddParam("c"new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
            engine.AddParam("d"new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
            engine.AddParam("e"new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
            engine.AddParam("f"new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
            engine.AddParam("g"new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
            engine.AddParam("h"new int[] { 1, 2, 3, 4, 5, 6, 7, 8 });
  
            engine.AddRequire((int a, int b, int c, int d, int e, int f, int g, int h) =>
                a != b && a != c && a != d
                && a != e && a != f && a != g && a != h
                && b != c && b != d && b != e && b != f && b != g && b != h
                && c != d && c != e && c != f && c != g && c != h
                && d != e && d != f && d != g && d != h
                && e != f && e != g && e != h
                && f != g && f != h
                && g != h
                && NotInTheSameDiagonalLine(new int[] { a, b, c, d, e, f, g, h }));
  
            engine.EachResult(
               result =>
                   Console.WriteLine("(1,{0}), (2,{1}), (3,{2}), (4,{3}), (5,{4}), (6,{5}), (7,{6}), (8,{7})"
                   result["a"],
                   result["b"],
                   result["c"],
                   result["d"],
                   result["e"],
                   result["f"],
                   result["g"],
                   result["h"])
                   );
        
  
        static bool NotInTheSameDiagonalLine(int[] cols)
        
            for (int i = 0; i < cols.Length - 1; i++)
            
                for (int j = i + 1; j < cols.Length; j++)
                
                    if (j - i == Math.Abs(cols[j] - cols[i]))
                        return false
                
            
            return true
        
  
        public static void Benchmarking(Action f, string messageFormat)
        
            DateTime time1 = DateTime.Now;
            f();
            DateTime time2 = DateTime.Now;
            Console.WriteLine(messageFormat, (time2 - time1).TotalMilliseconds);
        
    
}
view source

print?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
  
namespace NonDeterministicEngineCS
    public class Param
    
        public string Name
        
            get
            set
        
        public IEnumerator Values
        
            get
            set
        
    
}
view source

print?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
  
namespace NonDeterministicEngineCS
    public abstract class Condition
    
        public IList<string> ParamNames
        
            get
            protected set
        
          
        public abstract bool Call(params object[] args);
  
        public Condition(Delegate predicate)
        
            ParamNames = predicate.Method.GetParameters().Select(p => p.Name).ToArray();
        
    
  
    public class Condition<T> : Condition
    
        public Condition(Func<T, bool> predicate)
            base(predicate)
        
            m_func = predicate;
        
  
        Func<T, bool> m_func;
  
        public override bool Call(params object[] args)
        
            return m_func((T)args[0]);
        
    
  
    public class Condition<T1, T2> : Condition
    
        public Condition(Func<T1, T2, bool> predicate)
            base(predicate)
        
            m_func = predicate;
        
  
        Func<T1, T2, bool> m_func;
  
        public override bool Call(params object[] args)
        
            return m_func((T1)args[0], (T2)args[1]);
        
    
  
    public class Condition<T1, T2, T3> : Condition
    
        public Condition(Func<T1, T2, T3, bool> predicate)
            base(predicate)
        
            m_func = predicate;
        
  
        Func<T1, T2, T3, bool> m_func;
  
        public override bool Call(params object[] args)
        
            return m_func((T1)args[0], (T2)args[1], (T3)args[2]);
        
    
  
    public class Condition<T1, T2, T3, T4> : Condition
    
        public Condition(Func<T1, T2, T3, T4, bool> predicate)
            base(predicate)
        
            m_func = predicate;
        
  
        Func<T1, T2, T3, T4, bool> m_func;
  
        public override bool Call(params object[] args)
        
            return m_func((T1)args[0], (T2)args[1], (T3)args[2], (T4) args[3]);
        
    
  
    public class Condition<T1, T2, T3, T4, T5> : Condition
    
        public Condition(Func<T1, T2, T3, T4, T5, bool> predicate)
            base(predicate)
        
            m_func = predicate;
        
  
        Func<T1, T2, T3, T4, T5, bool> m_func;
  
        public override bool Call(params object[] args)
        
            return m_func((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4]);
        
    
  
    public class Condition<T1, T2, T3, T4, T5, T6> : Condition
    
        public Condition(Func<T1, T2, T3, T4, T5, T6, bool> predicate)
            base(predicate)
        
            m_func = predicate;
        
  
        Func<T1, T2, T3, T4, T5, T6, bool> m_func;
  
        public override bool Call(params object[] args)
        
            return m_func((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4], (T6)args[5]);
        
    
  
    public class Condition<T1, T2, T3, T4, T5, T6, T7> : Condition
    
        public Condition(Func<T1, T2, T3, T4, T5, T6, T7, bool> predicate)
            base(predicate)
        
            m_func = predicate;
        
  
        Func<T1, T2, T3, T4, T5, T6, T7, bool> m_func;
  
        public override bool Call(params object[] args)
        
            return m_func((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4], (T6)args[5], (T7)args[6]);
        
    
  
    public class Condition<T1, T2, T3, T4, T5, T6, T7, T8> : Condition
    
        public Condition(Func<T1, T2, T3, T4, T5, T6, T7, T8, bool> predicate)
            base(predicate)
        
            m_func = predicate;
        
          
        Func<T1, T2, T3, T4, T5, T6, T7, T8, bool> m_func;
  
        public override bool Call(params object[] args)
        
            return m_func((T1)args[0], (T2)args[1], (T3)args[2], (T4)args[3], (T5)args[4], (T6)args[5], (T7)args[6], (T8)args[7]);
        
    
}
view source

print?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading.Tasks;
using System.Linq.Expressions;
  
namespace NonDeterministicEngineCS
    public class NonDeterministicEngine
    
        private List<Param> m_paramDict = new List<Param>();
        private List<Condition> m_predicateDict = new List<Condition>();
  
        public void AddParam(string name, IEnumerable values)
        
            m_paramDict.Add(new Param { Name = name, Values = values.GetEnumerator() });
        
  
        #region Add Require
        public void AddRequire<T>(Func<T, bool> predicate)
        
            m_predicateDict.Add(new Condition<T>(predicate));
        
  
        public void AddRequire<T1, T2>(Func<T1, T2, bool> predicate)
        
            m_predicateDict.Add(new Condition<T1, T2>(predicate));
        
  
        public void AddRequire<T1, T2, T3>(Func<T1, T2, T3, bool> predicate)
        
            m_predicateDict.Add(new Condition<T1, T2, T3>(predicate));
        
  
        public void AddRequire<T1, T2, T3, T4>(Func<T1, T2, T3, T4, bool> predicate)
        
            m_predicateDict.Add(new Condition<T1, T2, T3, T4>(predicate));
        
  
        public void AddRequire<T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5, bool> predicate)
        
            m_predicateDict.Add(new Condition<T1, T2, T3, T4, T5>(predicate));
        
  
        public void AddRequire<T1, T2, T3, T4, T5, T6>(Func<T1, T2, T3, T4, T5, T6, bool> predicate)
        
            m_predicateDict.Add(new Condition<T1, T2, T3, T4, T5, T6>(predicate));
        
  
        public void AddRequire<T1, T2, T3, T4, T5, T6, T7>(Func<T1, T2, T3, T4, T5, T6, T7, bool> predicate)
        
            m_predicateDict.Add(new Condition<T1, T2, T3, T4, T5, T6, T7>(predicate));
        
  
        public void AddRequire<T1, T2, T3, T4, T5, T6, T7, T8>(Func<T1, T2, T3, T4, T5, T6, T7, T8, bool> predicate)
        
            m_predicateDict.Add(new Condition<T1, T2, T3, T4, T5, T6, T7, T8>(predicate));
        
        #endregion
  
        public IEnumerable<Dictionary<stringobject>> GetResults()
        
            var em = new CombinationEnumerable(this);
  
            foreach (var item in em)
            
                if (Satisfy(item))
                    yield return item;
            
        
  
        public void EachResult(Action<Dictionary<stringobject>> action)
        
            var em = new CombinationEnumerable(this);
  
            Parallel.ForEach(
                em,
                result =>
                
                    if (Satisfy(result))
                    
                        action(result);
                    
                
            );
        
          
        bool Satisfy(Dictionary<stringobject> result)
        
            foreach (Condition item in m_predicateDict)
            
                var args = item.ParamNames.Select(
                    name => result[name]
                        ).ToArray();
  
                if (item.Call(args))
                    continue
  
                return false
            
            return true
        
          
        private class CombinationEnumerable : IEnumerable<Dictionary<stringobject>>
        
            NonDeterministicEngine m_engine;
  
            public CombinationEnumerable(NonDeterministicEngine engine)
            
                m_engine = engine;
            
  
            public IEnumerator<Dictionary<stringobject>> GetEnumerator()
            
                return new CombinationEnumerator(m_engine);
            
  
            IEnumerator IEnumerable.GetEnumerator()
            
                return new CombinationEnumerator(m_engine);
            
        
  
        /// <summary>
        /// 组合多个 iterator 为一个复合的 iterator.
        /// MoveNext 实现为:移动到下一个所有变量值可能的组合。
        /// </summary>
        private class CombinationEnumerator : IEnumerator<Dictionary<stringobject>>
        
            private bool m_firstTime = true
            private NonDeterministicEngine m_target;
  
            public CombinationEnumerator(NonDeterministicEngine engine)
            
                m_target = engine;
            
  
            public void Dispose()
            
            
  
            public Dictionary<stringobject> GetCurrent()
            
                if (IterationOver)
                    return null
  
                return m_target.m_paramDict.ToDictionary
                    (param => param.Name, param => param.Values.Current);
            
  
            public bool MoveNext()
            
                if (IterationOver)
                    return false
  
                if (m_firstTime)
                
                    // 首次执行时,需要将所有变量的 enumerator 都前进到起始位置
                    foreach (Param item in m_target.m_paramDict)
                    
                        item.Values.MoveNext();
                    
                    m_firstTime = false
                    return true
                
  
                // 首先尝试最后一个变量的 iterator,看能否 MoveNext() (是否还有没有尝试过的值)。
                int iterIndex = m_target.m_paramDict.Count - 1;
                bool canMoveNext = m_target.m_paramDict[iterIndex].Values.MoveNext();
                if (canMoveNext)
                    return true
  
                // 否则依次回溯到前一个变量,看该变量的 iterator 能否 MoveNext()
                while (!canMoveNext)
                
                    iterIndex--;
  
                    // 表明已尝试了所有变量的所有可能值,退无可退,则终止枚举过程。
                    if (iterIndex == -1)
                    
                        IterationOver = true
                        return false
                    
  
                    canMoveNext = m_target.m_paramDict[iterIndex].Values.MoveNext();
                    // 如果往前退到某个可以前进的位置
                    if (canMoveNext)
                    
                        // 则需要将这个位置之后的所有其他变量的 iterator 复位,并前进到第一种可能性。
                        for (int i = iterIndex + 1; i < m_target.m_paramDict.Count; i++)
                        
                            var iter = m_target.m_paramDict[i].Values;
                            iter.Reset();
                            iter.MoveNext();
                        
                        return true
                    
                
                return false
            
              
            public void Reset()
            
                IterationOver = false
                m_firstTime = true
  
                foreach (var param in m_target.m_paramDict)
                
                    param.Values.Reset();
                
            
  
            public Dictionary<stringobject> Current
            
                get
                
                    return GetCurrent();
                
            
              
            /// <summary>
            /// 标记枚举是否已经结束
            /// </summary>
            public bool IterationOver
            
                get
                set
            
  
            object IEnumerator.Current
            
                get
                
                    return GetCurrent();
                
            
        
    
}

非确定性计算引擎转化为C#版本并重构的更多相关文章

  1. Spark源码剖析 - 计算引擎

    本章导读 RDD作为Spark对各种数据计算模型的统一抽象,被用于迭代计算过程以及任务输出结果的缓存读写.在所有MapReduce框架中,shuffle是连接map任务和reduce任务的桥梁.map ...

  2. 【Spark深入学习 -13】Spark计算引擎剖析

    ----本节内容------- 1.遗留问题解答 2.Spark核心概念 2.1 RDD及RDD操作 2.2 Transformation和Action 2.3 Spark程序架构 2.4 Spark ...

  3. 基于Kafka的实时计算引擎如何选择?Flink or Spark?

    1.前言 目前实时计算的业务场景越来越多,实时计算引擎技术及生态也越来越成熟.以Flink和Spark为首的实时计算引擎,成为实时计算场景的重点考虑对象.那么,今天就来聊一聊基于Kafka的实时计算引 ...

  4. 基于Kafka的实时计算引擎如何选择?(转载)

    1.前言 目前实时计算的业务场景越来越多,实时计算引擎技术及生态也越来越成熟.以Flink和Spark为首的实时计算引擎,成为实时计算场景的重点考虑对象.那么,今天就来聊一聊基于Kafka的实时计算引 ...

  5. 交互式计算引擎REOLAP篇

    交互式计算引擎ROLAP篇   摘自:<大数据技术体系详解:原理.架构与实践> 一.Impala Impala最初由Cloudera公司开发的,其最初设计动机是充分结合传统数据库与大数据系 ...

  6. 腾讯大数据之TDW计算引擎解析——Shuffle

    转自 https://www.csdn.net/article/2014-05-19/2819831-TDW-Shuffle/1 摘要:腾讯分布式数据仓库基于开源软件Hadoop和Hive进行构建,T ...

  7. Flink学习笔记-新一代Flink计算引擎

    说明:本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKh ...

  8. Fel表达式计算引擎学习

    转载原文地址:Fel是轻量级的高效的表达式计算引擎 Fel的问题 Fel的问题 Fel是轻量级的高效的表达式计算引擎 Fel在源自于企业项目,设计目标是为了满足不断变化的功能需求和性能需求. Fel是 ...

  9. 《大数据实时计算引擎 Flink 实战与性能优化》新专栏

    基于 Flink 1.9 讲解的专栏,涉及入门.概念.原理.实战.性能调优.系统案例的讲解. 专栏介绍 扫码下面专栏二维码可以订阅该专栏 首发地址:http://www.54tianzhisheng. ...

随机推荐

  1. Redis Windows版安装详解

    一.下载Redis Redis下载有两个途径一是官网.二是Github,由于Redis官方只支持Linux系统,所以官网是没有Windows版本的,不过微软开源团队维护了一份所以我们可以使用这个. 官 ...

  2. 华为olt ma5680t常用命令详解

    进入待替换的故障ONU所注册的单板 interface epon 0/1         //此处可以通过查看PON口下设备状态来获取需要替换的ONU ID.假设故障设备位于2端口,ID为6 ont ...

  3. Oracle 之——子查询 DDL DML 集合 及其他数据对象

    Oracle 学习笔记(二) 知识概要: 1.子查询 2.集合操作 3.DML语句操作 4.其他数据库对象 1.子查询 查询工资比SCOTT高的员工信息 1  select * 2  from emp ...

  4. Vue实现选项卡切换

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  5. ASP.NET MVC AJAX的调用示例

    @{ ViewBag.Title = "Home Page"; //下面引用Jquery和unobtrusive-ajax } @Scripts.Render("~/bu ...

  6. PHP多进程编之僵尸进程问题

    上一篇说到了使用pcntl_fork函数可以让PHP实现多进程并发或者异步处理的效果.那么问题是我们产生的进程需要去控制,而不能置之不理.最基本的方式就是fork进程和杀死进程. 通过利用pcntl_ ...

  7. DevOps之唠叨话

    唠叨话 教学:人类培养态度.传授知识.训练技能的活动. 教学手册(Teaching Manual) 教学形式:教材与课程,师生(一对一.一对多).教学内容:系统框架和问答机制,结构(前言.目录.正文. ...

  8. 使用MVVM减少控制器代码实战(减少56%)

    减少比例= (360(原来的行数)-159(瘦身后的行数))/360 = 56% 父类 MVC 和MVVM 前后基本不动 父类主要完成如下三个功能: 1)功能:MJRefrsh +上拉下拉没有更多数据 ...

  9. wpf GifBitmapDecoder 解析 gif 格式

    在网上有很多图片都是gif,那么如何在 wpf 解析 gif? 本文告诉大家如何使用 GifBitmapDecoder 把gif分开为一张一张,获得他的信息. 如果需要把一个 gif 分开,使用的代码 ...

  10. Learning Scrapy 中文版翻译 第一章

    第一章:scrapy介绍 欢迎来到scrapy之旅.通过这本书,我们将帮助你从只会一点或者零基础的Scrapy初学者达到熟练使用这个强大的框架在互联网或者其他资源抓取海量的数据.在这一章节,我们将给你 ...