Zulip Chat Archive

Stream: Is there code for X?

Topic: set like equivalence of lists without converting to finsets


Jared green (Oct 21 2025 at 16:09):

is there an equivalent of

l1 : List a
l2 : List a
l1   l2 && l2  l1

other than

List.isPerm l1 l2

that will work on lists of different lengths and different numbers of duplicates

Kenny Lau (Oct 21 2025 at 16:11):

I don't think they're equivalent

Kenny Lau (Oct 21 2025 at 16:11):

but why do you need such a predicate?

Kenny Lau (Oct 21 2025 at 16:11):

can you give us more context?

Jared green (Oct 21 2025 at 16:18):

i know they arent exactly the same, but i asked the same question earlier and isPerm is the answer i got, but it turned out not to be general enough for what i was doing. a shorter form of 'they are subsets of each other' would shorten my code a bit. and i dont want to have to import finset unnecessarily.

Kenny Lau (Oct 21 2025 at 16:18):

what is your code doing?

Jared green (Oct 21 2025 at 16:28):

restricted resolution where the literals in the clause pairs are the same but just one has opposing polarity. the rest of resolution is done elsewhere

import Batteries.Data.List.Basic
import Mathlib.Data.List.Defs
import Mathlib.Order.Defs.PartialOrder
import Mathlib.Data.List.Sublists

def Clause := List (Nat × Bool) deriving DecidableEq, Membership
variable {a : Type}
variable {toProp : Nat -> Prop}

def isResolvable (c1 c2 : Clause) : Bool :=
  let lits1 := c1.map (·.1)
  let lits2 := c2.map (·.1)
  lits1   lits2 && lits2  lits1 &&
  (c1.product c2).all₂ (fun l1 l2 => (l1.1.1 = l1.2.1 && l2.1.1 = l2.2.1  &&
  l1.1.2 != l1.2.2 && l2.1.2 != l2.2.2)  -> l1.1.1 = l2.1.1) (c1.product c2)

def generateResolvents (clauses : List Clause) : List Clause :=
  List.flatten (
    List.map (fun c1 =>
      (List.filter
      (fun c2 => c1 == c2 || isResolvable c1 c2) clauses).map
      (fun c2 => c1.inter c2)
      ) clauses)

Jakub Nowak (Oct 21 2025 at 23:17):

What's wrong with converting to finsets?

Yury G. Kudryashov (Oct 21 2025 at 23:22):

If you don't care about multiplicities, then you can say {x | x ∈ l1} = {x | x ∈ l2}.

Jakub Nowak (Oct 21 2025 at 23:29):

Yury G. Kudryashov said:

If you don't care about multiplicities, then you can say {x | x ∈ l1} = {x | x ∈ l2}.

That's undecidable though.

Jakub Nowak (Oct 21 2025 at 23:39):

But l0.toFinset = l1.toFinset is decidable.

Jared green (Oct 22 2025 at 14:09):

nothing in particular is wrong with converting to finset, however given that every other set operation and predicate has a functional equivalent for lists that doesn't do such a conversion(except existsunique), why wouldn't this one?

Jakub Nowak (Oct 22 2025 at 18:55):

You should think about what gives most readable code. For me l0.toFinset = l1.toFinset is easy to understand. I don't think l0.eqAsSets l1 is better, because it pretty much says exactly the same, but in english. Unless you can come up with a better name for this property, I don't see much need for this.


Last updated: Dec 20 2025 at 21:32 UTC