carbon icon indicating copy to clipboard operation
carbon copied to clipboard

Potential incompleteness with postcondition for mutually recursive functions

Open mschwerhoff opened this issue 9 months ago • 0 comments

Carbon fails to verify the postcondition of function coin_rec(), while it verifies in Silicon.

function min(a: Int, b: Int) : Int
  decreases a, b
{
  a < b ? a : b
}

// Predicate to check if the weights and values sequences are valid for the knapsack problem
define valid_coin_seq(coins) 
  |coins| >= 2 &&
  forall k: Int :: {coins[k]} 0 <= k < |coins| ==> coins[k] > 0

function coin_rec(amount: Int, coins: Seq[Int]) : Int
  requires valid_coin_seq(coins) // Required for termination
  ensures amount < 0 ==> result == -1 // ❌ Failing postcondition (in Carbon)
  decreases amount // Holds, but does not seem to affect verification behaviour
{
  amount == 0 ? 0 : minCoinsHelper(amount, |coins|, coins)
}


function minCoinsHelper(amount: Int, index: Int, coins: Seq[Int]) : Int 
  requires 0 <= index <= |coins|
  requires valid_coin_seq(coins) // Required for termination
  decreases amount, index // Holds, but does not seem to affect verification behaviour
{
  (amount == 0 ) ? 0 :
  (amount < 0 || index == 0) ? -1 :
  
  // If next two lines are commented and the last is replaced by 0, Carbon verifies the problematic postcondition
  (coin_rec(amount - coins[index-1], coins) == -1) ? minCoinsHelper(amount, index - 1, coins) : // Only this line commented ➜ error in Silicon
  (minCoinsHelper(amount, index - 1, coins) == -1) ? 1 + coin_rec(amount - coins[index-1], coins) : // Only this line (or this and the preceding line) commented ➜ Silicon OK
  
  min(1 + coin_rec(amount - coins[index-1], coins), minCoinsHelper(amount, index - 1, coins))
}

I could imagine that the problem/difference in verifiers is due to the order in which information becomes available during the verification of the mutually recursive functions.

The problem was originally reported by Sonja Joost.

mschwerhoff avatar Apr 04 '25 13:04 mschwerhoff