예제 #1
0
파일: DPLL.cs 프로젝트: Popa611/SAT-solver
        public async Task <DPLLResultHolder> SatisfiableParallel(CNF cnf)
        {
            parallel = true;

            sharedModelQueue.Clear();
            sharedModelQueue.Enqueue(cnf);  // Initial formula (model) to solve

            List <Task <DPLLResultHolder> > taskList = new List <Task <DPLLResultHolder> >();

            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            var token = cancellationTokenSource.Token;

            var idleThreadsCounter = new IdleThreadsCounter();

            for (int i = 0; i < Environment.ProcessorCount; i++)
            {
                taskList.Add(Task.Run(() => Solve(this, sharedModelQueue, idleThreadsCounter, token), token));
            }

            var taskArray = taskList.ToArray();
            var finalTask = await Task.WhenAny(taskArray);

            cancellationTokenSource.Cancel();   // Cancel other tasks still solving SAT
            lock (sharedModelQueue)
            {
                Monitor.PulseAll(sharedModelQueue); // Wake tasks waiting at the queue, so they can cancel
            }

            parallel = false;

            return(await finalTask);
        }
예제 #2
0
파일: DPLL.cs 프로젝트: Popa611/SAT-solver
        // Each thread's "main" function
        private DPLLResultHolder Solve(DPLL parallelDPLL, Queue <CNF> sharedModelQueue, IdleThreadsCounter idleThreadsCounter, CancellationToken token)
        {
            CNF model;

            while (true)
            {
                lock (sharedModelQueue)
                {
                    while (sharedModelQueue.Count == 0)
                    {
                        Monitor.Wait(sharedModelQueue); // Wait if there's nothing to solve
                        token.ThrowIfCancellationRequested();
                    }

                    Interlocked.Decrement(ref idleThreadsCounter.Counter); // This task started working - is no longer idle
                    model = sharedModelQueue.Dequeue();                    // Get a CNF model from the shared queue
                }

                token.ThrowIfCancellationRequested();
                DPLLResultHolder solverThreadResult = parallelDPLL.Satisfiable(model);

                if (solverThreadResult.SAT)
                {
                    return(solverThreadResult);  // The task has found SAT model
                }
                else
                {
                    Interlocked.Increment(ref idleThreadsCounter.Counter);  // The task is idle for now
                }

                lock (sharedModelQueue)
                {
                    // If all threads are idle and the queue is empty -> we're done and result remains unsat
                    if (Interlocked.Read(ref idleThreadsCounter.Counter) == Environment.ProcessorCount && sharedModelQueue.Count == 0)
                    {
                        return(solverThreadResult);
                    }
                }
            }
        }