NVMを使用して、中止された場合は常に粘り強く操作を再開します


8

これまでの動作を記憶し、再実行が中止された場合に目標に向けて継続するプログラムを作成しようとしています。これは粘り強いプログラムです。これは、不揮発性メモリを使用して、実行全体の情報をいくつかのcitとして格納します。これは、アボート時に発生することを考慮したビットです。私はかつて、N citsを使用して、いくつかの小さな固定Kで長さ2 (NK)までの任意の目標が達成可能であると推測しました。今、目標を達成できないと考えることに傾倒しています:-(

目標粘り強いプログラムに尋ねられましたが、それはすでに重要な目標です 01ます。または不可能性の厳密な証拠。

粘り強いプログラムは、1そのように定義されます。

  1. runを実行するときは常に、入力なしで同じエントリポイントから実行を実行し、N cits(以下で定義)のみを使用してrun間で情報を共有できます。他のすべての情報は、各実行の開始時に同じ内容であるか、実行の開始時に予測できない内容であるか、変更できない(プログラム自体)か、読み取り不可能(以前の出力)のいずれかです。
  2. セッション内で実行すると、その言語の機能を使用して、実行が開始されてからある程度の遅延の範囲内で、中止されない限り、明らかに停止します。前に中止さに停止します。アボートは任意の瞬間に発生し、別の実行(ある場合)まで操作を阻止します。
  3. それが出力する文字の時系列での連結は、プログラムが停止するまで実行されたままの少なくとも1つの実行を含む任意のセッションの任意のセッションで同じ有限文字列(目標)と同じです。
  4. 出力は、そのデバイスを使用して文字アトミックは:受信 0 1 2 3の間で PUTをプログラムすることによって、出力0(それぞれ1)の値を0または2(それぞれ1または3)の間であれば、その値は、以前と異なる場合にのみ値プット。セッションの最初のプットでは0と見なされます。

粘り強いプログラムが存在します!有効な固定値を固定回数だけ単純に入力してから停止するプログラムは、目標が空(数値または値が0の0場合)、(数値が正で値が2の場合)、または1(それ以外の場合)粘り強くなります。それ以上の目標にはNVMが必要です。

citは、citへの書き込み中に中止された実行の影響を考慮して、1つのNVMビットをモデル化します。いつでも、citは3つの可能な状態の0 1いずれかになりUます。citから読み取られる値は常に0または1です。それ以外の場合も州と一致しますU。citは0セッションでの最初の実行前の状態に初期化されます。それ以外の場合は、プログラムによる書き込みがコマンドによって指示されたときにのみ状態が変化します。これは、書き込まれた内容、書き込み中に実行が中止されたかどうか、およびcitの以前の状態:

         Former state  0   1   U    Rationale given by hardware guru
Operation
  Write 0 completed    0   0   0    Discharging returns cit to 0
  Write 0 aborted      0   U   U    Aborted discharging leaves cit unspecified
  Write 1 aborted      U   1   U    Aborted    charging leaves cit unspecified
  Write 1 completed    1   1   U    Charging a non-discharged cit is inhibited

上記のHALは、Cで次のように宣言されています。

/* file "hal.h"              unspecified parameter values give undefined behavior */
#define  N 26                       /* number of  cits                            */
void     p(unsigned v);             /* put value v; v<4                           */
unsigned r(unsigned i);             /* read from  cit at i; returns 0 or 1;  i<N. */
void     w(unsigned i, unsigned b); /* write b to cit at i;    b is 0 or 1;  i<N. */
/*                            all functions return in bounded time unless aborted */

目標を掲げた粘り強いプログラムでの最初の試み01は次のとおりです。

#include "hal.h"                    /* discount this line's length                */
main(){                             /* entry point, no parameters or input        */
    if (r(3)==0)                    /* cit 3 read as 0, that is state 0 or U      */
        w(3,0),                     /* write 0 to cit 3, to ensure state 0        */
        p(2);                       /* put 2 with output '0' initially            */
    w(3,1),                         /* mark we have output '0' (trouble spot!)    */
    p(1);                           /* put 1 with output '1'                      */
}                                   /* halt (but we can be re-run)                */

マーフィーは最初のセッションを作成し、最初の実行を停止してセッションを終了します。セッションの出力は単一実行の出力01です。ここまでは順調ですね。
別のセッションで、マーフィーはの最初の実行を中止し、w(3,1)citを状態のままにしますU。2回目の実行では、マーフィーはそれr(3)を1(citは状態にあるU)と決定し、プログラムの実行を停止します(w(3,1)citの状態がどのように変更されなかったかに注意してください)。3回目の実行で、マーフィーはそれr(3)を0と決定し、の後p(2)で打ち切り、セッションを終了します。
2番目のセッションの連結出力は010(実行ごとに1文字)ですが01、最初のセッションとは異なるため、プログラムは粘り強くなく、条件3が満たされていません。


言語は無料です。言語に合わせてCインターフェイスを調整してください。私は、使用されるcitの最小数に基づいて最良の答えを選択します。次に、実行から出力(または出力がない場合は停止)への書き込みの最悪の場合の最小数。次に、打ち切りなしのセッションで停止する前の書き込みの最小数。次に最短のプログラム。呼び出しコードのみをカウントし、インターフェースやその実装はカウントしません。これは不要です。不可能性の厳密な証明はプログラムを排除します(そして私には驚きです)。把握するのに最も簡単なものを選択します。

中止の数と瞬間に関係なく、プログラムが3の目標を本当に達成していることをトリプルチェックしてください。難しい!

更新:候補者の回答を追加しました。それを切り捨ててください。ああ、ハンマーは体系的なプログラムを使用して数分でそれを行いました!

ステータス:これまでのところ、解決策はありません。1つまたは2つのcitで解決策がないことを確実に知ってください。しかし、3つ以上のcitで不可能であることの証明はありません。この文はあいまいではありません。citマトリックスをわずかに変更した場合(たとえば、右下を1にすると、上記の例が正しい場合)、問題は解決します。


同様の質問がされたように感じます-おそらくフラッシュメモリ/電力サージにもっと関連していると思います-しかし、それを見つけることができないようです。
Gaffi

1
@Gaffi:2週間前に、Pi-3の2進数の小数に対して同様のプロパティを持つプログラムに、citsの数やその他のものを考慮して、可能な最大長まで、中止ではなく停電という言葉で質問しました。有効な答えをどのように決定するかを尋ねる(肯定的な)批判に会った。私はできないと思い、質問を削除しました。この細心の注意を払って書かれたコードゴルフにより、私はプログラムをチェックしたり、多くの言語でより粘り強いプログラムを投稿したりできると確信しています。私の唯一の後悔は、目標を少しセクシーにすべきだったということです。
fgrieu

1
これをコードゴルフにしてよろしいですか?このようなプログラムを作成すること(そしてその正確性を証明すること)が課題であるように思えます。それが完了すると、ゴルフはかなり些細な練習になります(インターフェイスを調整することが許可されているため、やや不明確です)。たぶん代わりにそれをコードチャレンジにしますか?
Ilmari Karonen 2012

別の質問:自明ではない粘り強いプログラムの不可能性を証明することが解決策として数えられるでしょうか?(まだそのような証拠はありませんが、そうかもしれないと私は考え始めています。)
Ilmari Karonen 2012

@IlmariKaronen:不可能性の証明は王様です!有効な解決策を投稿しました。自分で見て。
fgrieu

回答:


6

私には解決策も不可能性の証明もありませんが、私はこの時点でほとんどあきらめているので、これをいじりたい人のためにテストハーネスを投稿すると思いました。

これは、HaskellモナドとしてのHALモデリングプログラムの実装です。可能性のあるセッションに対して幅優先検索を実行して粘り強さをチェックし、1。正しい出力を生成せずに1回停止したか、2。目的のセッションのプレフィックスではない出力を生成したセッションをチェックします(これは無限の出力を生成するプログラムもキャッチします)。

{-# LANGUAGE GADTs #-}

module HAL where

import Control.Monad
import Data.List

import Data.Map (Map)
import qualified Data.Map as Map

import Data.Set (Set)
import qualified Data.Set as Set

newtype CitIndex = Cit Int
  deriving (Eq, Ord, Show)

data CitState = Stable Int | Unstable
  deriving (Eq, Ord, Show)

data Program a where
  Return :: a -> Program a
  Bind :: Program a -> (a -> Program b) -> Program b
  Put :: Int -> Program ()
  Read :: CitIndex -> Program Int
  Write :: CitIndex -> Int -> Program ()
  Log :: String -> Program ()
  Halt :: Program ()

instance Monad Program where
  return = Return
  (>>=) = Bind

data Session = Session
  { cits :: Cits
  , output :: [Int]
  , lastPut :: Int
  , halted :: Bool
  } deriving (Eq, Ord, Show)

data Event
  = ReadE CitIndex Int
  | PutE Int
  | WriteSuccessE CitIndex Int
  | WriteAbortedE CitIndex Int
  | LogE String
  | HaltedE
  deriving (Eq, Ord, Show)

type Log = [(Event, Cits)]

check :: Program () -> Int -> [Int] -> IO ()
check program n goal =
  case tenacity (program >> Halt) goal of
    Tenacious  -> putStrLn "The program is tenacious."
    Invalid ss -> do
      putStrLn "The program is invalid. Example sequence:"
      forM_ (zip [1..] ss) $ \(i, (log, s)) -> do
        ruler
        putStrLn $ "Run #" ++ show i ++ ", Initial state: " ++ formatState n s
        ruler
        mapM_ (putStrLn . formatEvent n) log
  where ruler = putStrLn $ replicate 78 '='

run :: Program a -> Session -> [(Maybe a, Log, Session)]
run (Return x) s = [(Just x, [], s)]
run (Bind x f) s = do
  (r1, l1, s1) <- run x s
  case r1 of
    Just y  -> [(r2, l1 ++ l2, s2) | (r2, l2, s2) <- run (f y) s1]
    Nothing -> [(Nothing, l1, s1)]
run (Put x) s = [(Just (), [(PutE x, cits s)], s')]
  where s' | lastPut s /= x = s { lastPut = x, output = output s ++ [x `mod` 2] }
           | otherwise      = s
run (Read cit) s =
  case lookupCit cit (cits s) of
    Stable x -> [(Just x, [(ReadE cit x, cits s)], s)]
    Unstable -> [(Just x, [(ReadE cit x, cits s)], s) | x <- [0, 1]]
run (Write cit x) (s @ Session { cits = cits }) =
  [(Just (), [(WriteSuccessE cit x, completed)], s { cits = completed }),
   (Nothing, [(WriteAbortedE cit x, aborted  )], s { cits = aborted })]
  where state = lookupCit cit cits
        completed = updateCit cit newState cits 
          where newState = case (x, state) of
                             (0, _)        -> Stable 0
                             (1, Unstable) -> Unstable
                             (1, Stable _) -> Stable 1

        aborted = updateCit cit newState cits
          where newState = case (x, state) of
                             (0, Stable 0) -> Stable 0
                             (0, _)        -> Unstable
                             (1, Stable 1) -> Stable 1
                             (1, _)        -> Unstable
run (Halt) s = [(Just (), [(HaltedE, cits s)], s { halted = True })] 
run (Log msg) s = [(Just (), [(LogE msg, cits s)], s)]

newSession :: Session
newSession = Session
  { cits = initialCits
  , output = []
  , lastPut = 0
  , halted = False }

newtype Cits = Cits (Map CitIndex CitState)
  deriving (Eq, Ord, Show)

initialCits = Cits (Map.empty)

lookupCit :: CitIndex -> Cits -> CitState
lookupCit cit (Cits m) = Map.findWithDefault (Stable 0) cit m

updateCit :: CitIndex -> CitState -> Cits -> Cits
updateCit index (Stable 0) (Cits m) = Cits $ Map.delete index m 
updateCit index newState (Cits m) = Cits $ Map.insert index newState m

data Tenacity = Tenacious | Invalid [(Log, Session)]
  deriving (Eq, Ord, Show)

tenacity :: Program () -> [Int] -> Tenacity
tenacity program goal = bfs Set.empty [(newSession, [])]
  where
    bfs :: Set Session -> [(Session, [(Log, Session)])] -> Tenacity
    bfs visited [] = Tenacious
    bfs visited ((s, pred) : ss)
      | Set.member s visited = bfs visited ss
      | valid s   = bfs (Set.insert s visited) $ ss ++ [(s', (l, s) : pred) | (_, l, s') <- run program s]
      | otherwise = Invalid $ reverse (([], s) : pred)

    valid :: Session -> Bool
    valid Session { output = output, halted = halted }
      | halted    = output == goal
      | otherwise = output `isPrefixOf` goal

formatState :: Int -> Session -> String
formatState n s = "[cits: " ++ dumpCits n (cits s) ++ "] [output: " ++ dumpOutput s ++ "]"

formatEvent :: Int -> (Event, Cits) -> String
formatEvent n (event, cits) = pad (78 - n) text ++ dumpCits n cits 
  where text = case event of
                 ReadE (Cit i) x         -> "read " ++ show x ++ " from cit #" ++ show i
                 PutE x                  -> "put " ++ show x
                 WriteSuccessE (Cit i) x -> "wrote " ++ show x ++ " to cit #" ++ show i
                 WriteAbortedE (Cit i) x -> "aborted while writing " ++ show x ++ " to cit #" ++ show i
                 LogE msg                -> msg
                 HaltedE                 -> "halted"

dumpCits :: Int -> Cits -> String
dumpCits n cits = concat [format $ lookupCit (Cit i) cits | i <- [0..n-1]]
  where format (Stable i) = show i
        format (Unstable) = "U" 

dumpOutput :: Session -> String
dumpOutput s = concatMap show (output s) ++ " (" ++ show (lastPut s) ++ ")"

pad :: Int -> String -> String
pad n s = take n $ s ++ repeat ' '

OPがHaskellに変換したプログラムの例を次に示します。

import Control.Monad (when)

import HAL

-- 3 cits, goal is 01
main = check example 3 [0, 1]

example = do
  c <- Read (Cit 2)
  d <- Read (Cit c)
  when (0 == c) $ do
    Log "in first branch"
    Write (Cit 2) 0
    Write (Cit 1) 0
    Write (Cit 1) (1 - d)
    Write (Cit 2) 1
  Write (Cit 0) 0
  when (d == c) $ do
    Log "in second branch"
    Put 2
    Write (Cit 2) 0
  Write (Cit 0) 1
  Put 1

そして、これは対応する出力で、プログラムが粘り強くないことを示しています。

The program is invalid. Example sequence:
==============================================================================
Run #1, Initial state: [cits: 000] [output:  (0)]
==============================================================================
read 0 from cit #2                                                         000
read 0 from cit #0                                                         000
in first branch                                                            000
wrote 0 to cit #2                                                          000
wrote 0 to cit #1                                                          000
wrote 1 to cit #1                                                          010
wrote 1 to cit #2                                                          011
wrote 0 to cit #0                                                          011
in second branch                                                           011
put 2                                                                      011
wrote 0 to cit #2                                                          010
wrote 1 to cit #0                                                          110
put 1                                                                      110
halted                                                                     110
==============================================================================
Run #2, Initial state: [cits: 110] [output: 01 (1)]
==============================================================================
read 0 from cit #2                                                         110
read 1 from cit #0                                                         110
in first branch                                                            110
wrote 0 to cit #2                                                          110
wrote 0 to cit #1                                                          100
wrote 0 to cit #1                                                          100
aborted while writing 1 to cit #2                                          10U
==============================================================================
Run #3, Initial state: [cits: 10U] [output: 01 (1)]
==============================================================================
read 1 from cit #2                                                         10U
read 0 from cit #1                                                         10U
wrote 0 to cit #0                                                          00U
aborted while writing 1 to cit #0                                          U0U
==============================================================================
Run #4, Initial state: [cits: U0U] [output: 01 (1)]
==============================================================================
read 0 from cit #2                                                         U0U
read 0 from cit #0                                                         U0U
in first branch                                                            U0U
wrote 0 to cit #2                                                          U00
wrote 0 to cit #1                                                          U00
wrote 1 to cit #1                                                          U10
wrote 1 to cit #2                                                          U11
wrote 0 to cit #0                                                          011
in second branch                                                           011
put 2                                                                      011
wrote 0 to cit #2                                                          010
wrote 1 to cit #0                                                          110
put 1                                                                      110
halted                                                                     110
==============================================================================
Run #5, Initial state: [cits: 110] [output: 0101 (1)]
==============================================================================

4

誰かがこのプログラムのバグを見つけられない限り、関連するすべての2引用プログラムをチェックして拒否すると思います。

私は、すべての引用を読み取り、セットによって形成された数をオンにするプログラムを検討することで十分だと主張します。スイッチの各ブランチは、一連の書き込みと書き込みになります。同じ数値を2回以上分岐に入れたり、2番目の出力桁を最初の桁の前に置いたりすることは決してありません。(私は、ブランチの最初以外の最初の数字または最後以外の2番目の数字を出力する意味がないことを道徳的に確信していますが、今のところ、その単純化は避けています)。

次に、各ブランチには設定したいcitのターゲットセットがあり、0にしたいビットを0に、1にしたいビットを0に、次に1に設定することで、そのブランチに向かって移動します。これらの書き込み操作は、さまざまな方法で注文できます。その実行ですでに0に設定していないか、おそらくnopでない限り、ビットを1に設定しても意味がありません。

13680577296の可能なプログラムを考慮しています。単一のソリューションを見つけることなく、すべてをチェックするのに7時間弱かかる4コアマシンが必要でした。

import java.util.*;

// State is encoded with two bits per cit and two bits for the output state.
//    ... [c_2=U][c_2=1/U][c_1=U][c_1=1/U][output_hi][output_lo]
// Output state must progress 0->1->2.
// Instruction (= program branch) is encoded with three or four bits per step.
//      The bottom two bits are the cit, or 0 for output/loop
//      If they're 0, the next two bits are 01 or 10 for output state, or 11 for halt.
//      Otherwise the next two bits are the value to write to the cit.
public class CitBruteForcer implements Runnable {

    static final int[] TRANSITION_OK = new int[]{
        // Index: write curr_hi curr_lo
        0,  // write 0 to 0 => 0
        0,  // write 0 to 1 => 0
        0,  // write 0 to U => 0
        -1, // invalid input
        1,  // write 1 to 0 => 1
        1,  // write 1 to 1 => 1
        2,  // write 1 to U => U
        -1  // invalid input
    };
    static final int[] TRANSITION_ABORT = new int[]{
        // Index: write curr_hi curr_lo
        0,  // write 0 to 0 => 0
        2,  // write 0 to 1 => U
        2,  // write 0 to U => U
        -1, // invalid input
        2,  // write 1 to 0 => U
        1,  // write 1 to 1 => 1
        2,  // write 1 to U => U
        -1  // invalid input
    };

    private final int[] possibleInstructions;
    private final int numCits, offset, step;
    private long tested = 0;

    private CitBruteForcer(int numCits, int[] possibleInstructions, int offset, int step)
    {
        this.numCits = numCits;
        this.possibleInstructions = possibleInstructions;
        this.offset = offset;
        this.step = step;
    }

    public void run()
    {
        int numStates = 1 << numCits;
        int n = possibleInstructions.length;
        long limit = pow(n, numStates);

        for (long i = offset; i < limit; i += step) {
            // Decode as a base-n number.
            int[] instructions = new int[numStates];
            long tmp = i;
            for (int j = 0; j < numStates; j++, tmp /= n) instructions[j] = possibleInstructions[(int)(tmp % n)];
            Program p = new Program(numCits, instructions);
            if (p.test()) System.out.println("Candidate: " + i);
            tested++;
        }
    }

    public static void main(String[] args) {
        int numCits = 2;
        int numThreads = 4;
        int[] possibleInstructions = buildInstructions(numCits);

        int numStates = 1 << numCits;
        int n = possibleInstructions.length;
        System.out.println(n + " possible instructions");
        long limit = pow(n, numStates);

        CitBruteForcer[] forcers = new CitBruteForcer[numThreads];
        for (int i = 0; i < numThreads; i++) {
            forcers[i] = new CitBruteForcer(numCits, possibleInstructions, i, numThreads);
            new Thread(forcers[i]).start();
        }

        int pc = 0;
        while (pc < 100) {
            // Every 10 secs is easily fast enough to update
            try { Thread.sleep(10000); } catch (InterruptedException ie) {}

            long tested = 0;
            for (CitBruteForcer cbf : forcers) tested += cbf.tested; // May underestimate because the value may be stale
            int completed = (int)(100 * tested / limit);
            if (completed > pc) {
                pc = completed;
                System.out.println(pc + "% complete");
            }
        }
        System.out.println(limit + " programs tested");
    }

    private static int[] buildInstructions(int numCits) {
        int limit = (int)pow(3, numCits);
        Set<Integer> instructions = new HashSet<Integer>();
        for (int target = 0; target <= limit; target++) {
            int toSetZero = 0, toSetOne = 0;
            for (int i = 0, tmp = target; i < numCits; i++, tmp /= 3) {
                if (tmp % 3 == 0) toSetZero |= 1 << i;
                else if (tmp % 3 == 1) toSetOne |= 1 << i;
            }
            buildInstructions(0xc, toSetZero, toSetOne, false, false, instructions);
        }
        int[] rv = new int[instructions.size()];
        Iterator<Integer> it = instructions.iterator();
        for (int i = 0; i < rv.length; i++) rv[i] = it.next().intValue();
        return rv;
    }

    private static void buildInstructions(int suffix, int toSetZero, int toSetOne, boolean emitted0, boolean emitted1, Set<Integer> instructions)
    {
        if (!emitted1) {
            buildInstructions((suffix << 4) + 0x8, toSetZero, toSetOne, false, true, instructions);
        }
        if (!emitted0) {
            buildInstructions((suffix << 4) + 0x4, toSetZero, toSetOne, true, true, instructions);
        }
        if (toSetZero == 0 && toSetOne == 0) {
            instructions.add(suffix);
            return;
        }

        for (int i = 0; toSetZero >> i > 0; i++) {
            if (((toSetZero >> i) & 1) == 1) buildInstructions((suffix << 3) + 0x0 + i+1, toSetZero & ~(1 << i), toSetOne, emitted0, emitted1, instructions);
        }
        for (int i = 0; toSetOne >> i > 0; i++) {
            if (((toSetOne >> i) & 1) == 1) buildInstructions((suffix << 3) + 0x4 + i+1, toSetZero | (1 << i), toSetOne & ~(1 << i), emitted0, emitted1, instructions);
        }
    }

    private static long pow(long n, int k) {
        long rv = 1;
        while (k-- > 0) rv *= n;
        return rv;
    }

    static class Program {
        private final int numCits;
        private final int[] instructions;
        private final Set<Integer> checked = new HashSet<Integer>();
        private final Set<Integer> toCheck = new HashSet<Integer>();

        Program(int numCits, int[] instructions) {
            this.numCits = numCits;
            this.instructions = (int[])instructions.clone();
            toCheck.add(Integer.valueOf(0));
        }

        boolean test() {
            try {
                while (!toCheck.isEmpty()) checkNext();
            } catch (Exception ex) {
                return false;
            }

            // Need each reachable state which hasn't emitted the full output to be able to reach one which has.
            Set<Integer> reachable = new HashSet<Integer>(checked);
            for (Integer reached : reachable) {
                checked.clear();
                toCheck.clear();
                toCheck.add(reached);
                while (!toCheck.isEmpty()) checkNext();
                boolean emitted = false;
                for (Integer i : checked) {
                    if ((i.intValue() & 3) == 2) emitted = true;
                }
                if (!emitted) return false;
            }

            return true;
        }

        private void checkNext() {
            Integer state = toCheck.iterator().next();
            toCheck.remove(state);
            checked.add(state);
            run(state.intValue());
        }

        private void run(final int state) {
            // Check which instructions apply
            for (int i = 0; i < instructions.length; i++) {
                boolean ok = true;
                for (int j = 1; j <= numCits; j++) {
                    int cit = (state >> (2 * j)) & 3;
                    if (cit == 2 || cit == ((i >> (j-1)) & 1)) continue;
                    ok = false; break;
                }
                if (ok) run(state, instructions[i]);
            }
        }

        private void run(int state, int instruction) {
            while (true) {
                int cit = instruction & 3;
                if (cit == 0) {
                    int emit = (instruction >> 2) & 3;
                    if (emit == 3) break;
                    if (emit > (state & 3) + 1 || emit < (state & 3)) throw new IllegalStateException();
                    state = (state & ~3) | emit;
                    instruction >>= 4;
                }
                else {
                    int shift = 2 * cit;
                    int transitionIdx = (instruction & 4) + ((state >> shift) & 3);
                    int stateMasked = state & ~(3 << shift);
                    consider(stateMasked | (TRANSITION_ABORT[transitionIdx] << shift));
                    state = stateMasked | (TRANSITION_OK[transitionIdx] << shift);
                    instruction >>= 3;
                }
                // Could abort between instructions (although I'm not sure this is strictly necessary - this is "better" than the mid-instruction abort
                consider(state);
            }
            // Halt or loop.
            consider(state);
        }

        private void consider(int state) {
            if (!checked.contains(state)) toCheck.add(state);
        }
    }
}

出力の配置に関する私の仮定を使用すると、2 citプログラムの数は大幅に減少し、チェック時間は1分未満ですが、この仮定を使用しても、3 citプログラムの数は2 ^ 80を超えるか、または7時間でチェックされた2-citプログラムよりも約2 ^ 47倍高い係数。言い換えれば、力ずくで強制することは合理的ではありません。
Peter Taylor

0

これ自分の質問に答える上での最善の試みでした。要件3を満たしているかどうかは不明ですが、異議を申し立てる可能性があります。粘り強くありません:-(

/*  1 */    #include "hal.h"
/*  2 */    main(){
/*  3 */        unsigned c = r(2);  // get cit 2 into c
/*  4 */        unsigned d = r(c);  // get cit c into d
/*  5 */    // here if d==c then we have not output 1 yet  
/*  6 */    //              else we have     output 0   
/*  7 */        if (0==c)
/*  8 */            w( 2, 0 ),      // cit 2 to 0
/*  9 */            w( 1, 0 ),      // cit 1 to 0
/* 10 */            w( 1,!d ),      // cit 1 to complement of d
/* 11 */            w( 2, 1 );      // cit 2 to 1
/* 12 */        w( 0, 0 );          // cit 0 to 0
/* 13 */        if (d==c)
/* 14 */            p( 2 ),         // put 2, first one outputs 0
/* 15 */            w( 2, 0 );      // cit 2 to 0
/* 16 */        w( 0, 1 );          // cit 0 to 1
/* 17 */        p( 1 );             // put 1, first one outputs 1
/* 16 */    }                       // halt

2
私のテストプログラムは、それは粘り強いとは言いません。1.プログラムを最後まで実行します。出力:01、CITS: 110。2.#15の間に中止します。CITS: 10U。3. c = 1#12の間に読み取り、中止します。CITS: U0U。4.読み取りc = 0d = 0プログラムが印刷されます01再び。
Hammar

申し訳ありませんが、最初の打ち切りは#15ではなく#11にあるはずです。
ハンマー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.