import Mathlibnamespace OAInoncomputable sectionopen MeasureTheoryopen scoped BigOperatorsnamespace ContinuumCoulomb.BinaryEncodingabbrev BitString := List Boolstructure Codec (α : Type*) where encode : α → BitString read : BitString → α × BitString read_encode : ∀ x tail, read (encode x ++ tail) = (x, tail)def encodeDigits : BitString → BitString | [] => [false] | b :: bs => true :: b :: encodeDigits bsdef readDigits : BitString → BitString × BitString | true :: b :: bs => let (digits, tail) := readDigits bs; (b :: digits, tail) | false :: bs => ([], bs) | _ => ([], [])theorem readDigits_encode (digits tail : BitString) : readDigits (encodeDigits digits ++ tail) = (digits, tail) := by induction digits with | nil => rfl | cons b digits ih => simp only [encodeDigits, List.cons_append, readDigits, ih]def decodeDigits : BitString → ℕ | [] => 0 | b :: bs => Nat.bit b (decodeDigits bs)theorem decodeDigits_bits (n : ℕ) : decodeDigits n.bits = n := by induction n using Nat.binaryRec' with | zero => rfl | bit b n h ih => simp only [Nat.bits_append_bit n b h, decodeDigits, ih]def natural : Codec ℕ where encode n := encodeDigits n.bits read s := let (digits, tail) := readDigits s; (decodeDigits digits, tail) read_encode n tail := by simp only [readDigits_encode, decodeDigits_bits]def encodeUnary : ℕ → BitString | 0 => [false] | n + 1 => true :: encodeUnary ndef readUnary : BitString → ℕ × BitString | true :: s => let (n, tail) := readUnary s; (n + 1, tail) | false :: s => (0, s) | [] => (0, [])theorem readUnary_encode (n : ℕ) (tail : BitString) : readUnary (encodeUnary n ++ tail) = (n, tail) := by induction n with | zero => rfl | succ n ih => simp only [encodeUnary, List.cons_append, readUnary, ih]def unary : Codec ℕ where encode := encodeUnary read := readUnary read_encode := readUnary_encodedef integer : Codec ℤ where encode | Int.ofNat n => false :: natural.encode n | Int.negSucc n => true :: natural.encode n read | false :: s => let (n, tail) := natural.read s; (Int.ofNat n, tail) | true :: s => let (n, tail) := natural.read s; (Int.negSucc n, tail) | [] => (0, []) read_encode z tail := by cases z <;> simp only [List.cons_append, natural.read_encode]def pair {α β : Type*} (a : Codec α) (b : Codec β) : Codec (α × β) where encode x := a.encode x.1 ++ b.encode x.2 read s := let (x, t) := a.read s; let (y, u) := b.read t; ((x, y), u) read_encode x tail := by rcases x with ⟨x, y⟩ simp only [List.append_assoc, a.read_encode, b.read_encode]def readCount {α : Type*} (a : Codec α) : ℕ → BitString → List α × BitString | 0, s => ([], s) | n + 1, s => let (x, t) := a.read s; let (xs, u) := readCount a n t; (x :: xs, u)theorem readCount_encode {α : Type*} (a : Codec α) (xs : List α) (tail : BitString) : readCount a xs.length (xs.flatMap a.encode ++ tail) = (xs, tail) := by induction xs with | nil => rfl | cons x xs ih => simp only [List.length_cons, List.flatMap_cons, List.append_assoc, readCount, a.read_encode, ih]def list {α : Type*} (a : Codec α) : Codec (List α) where encode xs := natural.encode xs.length ++ xs.flatMap a.encode read s := let (n, t) := natural.read s; readCount a n t read_encode xs tail := by simp only [List.append_assoc, natural.read_encode, readCount_encode]def equiv {α β : Type*} (a : Codec α) (e : β ≃ α) : Codec β where encode x := a.encode (e x) read s := let (x, t) := a.read s; (e.symm x, t) read_encode x tail := by simp only [a.read_encode, e.symm_apply_apply]def sum {α β : Type*} (a : Codec α) (b : Codec β) : Codec (α ⊕ β) where encode | Sum.inl x => false :: a.encode x | Sum.inr y => true :: b.encode y read | false :: s => let (x, t) := a.read s; (Sum.inl x, t) | true :: s => let (y, t) := b.read s; (Sum.inr y, t) | [] => let (x, t) := a.read []; (Sum.inl x, t) read_encode x tail := by cases x <;> simp only [List.cons_append, a.read_encode, b.read_encode]end ContinuumCoulomb.BinaryEncodingnamespace Coulombopen scoped ENNReal Classical NNReal ComplexConjugateabbrev Space := EuclideanSpace ℝ (Fin 3)abbrev Configuration (n : ℕ) := EuclideanSpace ℝ (Fin n × Fin 3)abbrev Spins (n : ℕ) := Fin n → Fin 2structure Nuclei (M : ℕ) where nonempty : 0 < M position : Fin M → Space distinct : Function.Injective position charge : Fin M → ℝ charge_ge_one : ∀ j, 1 ≤ charge jnoncomputable def position {n : ℕ} (x : Configuration n) (i : Fin n) : Space := WithLp.toLp 2 (fun b => x (i, b))noncomputable def coulombKernel (x : Space) : ℝ := ‖x‖⁻¹noncomputable def attraction {M : ℕ} (S : Nuclei M) (x : Space) : ℝ := ∑ j, S.charge j * coulombKernel (x - S.position j)noncomputable def permute {n : ℕ} (p : Equiv.Perm (Fin n)) (x : Configuration n) : Configuration n := WithLp.toLp 2 (fun ib => x (p ib.1, ib.2))structure H1Vector (n : ℕ) where value : Spins n → Configuration n → ℂ gradient : Spins n → (Fin n × Fin 3) → Configuration n → ℂ value_L2 : ∀ s, MemLp (value s) 2 volume partial_L2 : ∀ s a, MemLp (gradient s a) 2 volume weak_partial : ∀ s a (φ : Configuration n → ℝ), ContDiff ℝ (⊤ : ℕ∞) φ → HasCompactSupport φ → (∫ x, value s x * (fderiv ℝ φ x (EuclideanSpace.single a 1) : ℂ)) = -(∫ x, gradient s a x * (φ x : ℂ))def Antisymmetric {n : ℕ} (ψ : H1Vector n) : Prop := ∀ (p : Equiv.Perm (Fin n)) (s : Spins n), ∀ᵐ x ∂volume, ψ.value (s ∘ p) (permute p x) = ((p.sign : ℤ) : ℂ) * ψ.value s xnoncomputable def mass {n : ℕ} (ψ : H1Vector n) : ℝ := ∑ s, ∫ x, ‖ψ.value s x‖ ^ 2noncomputable def kinetic {n : ℕ} (ψ : H1Vector n) : ℝ := (1 / 2 : ℝ) * ∑ s, ∑ a, ∫ x, ‖ψ.gradient s a x‖ ^ 2noncomputable def nuclearEnergy {M n : ℕ} (S : Nuclei M) (ψ : H1Vector n) : ℝ := ∑ s, ∫ x, (∑ i, attraction S (position x i)) * ‖ψ.value s x‖ ^ 2noncomputable def pairEnergy {n : ℕ} (ψ : H1Vector n) : ℝ := ∑ s, ∫ x, (∑ i : Fin n, ∑ j : Fin n, if i < j then coulombKernel (position x i - position x j) else 0) * ‖ψ.value s x‖ ^ 2noncomputable def form {M n : ℕ} (S : Nuclei M) (ψ : H1Vector n) : ℝ := kinetic ψ - nuclearEnergy S ψ + pairEnergy ψend Coulombnamespace ContinuumCoulombopen BinaryEncoding Matrixopen scoped Kroneckerabbrev SourceSpinBasis (n : ℕ) := Fin n → Fin 2def sourceTensor (n : ℕ) (M : Fin n → Matrix (Fin 2) (Fin 2) ℂ) : Matrix (SourceSpinBasis n) (SourceSpinBasis n) ℂ := fun s t => ∏ i, M i (s i) (t i)sectiontheorem bellScale_atLeastTwo : Nat.AtLeastTwo (1 + 1) := @Nat.instAtLeastTwoHAddOfNat 1 (@Nat.instNeZeroSucc 0)attribute [local instance] bellScale_atLeastTwodef bellScale : ℂ := (Real.sqrt (1 / 2 : ℝ) : ℂ)endinductive QMAGate where | hadamard (qubit : ℕ) | phaseT (qubit : ℕ) | controlledNot (control target : ℕ) deriving DecidableEq, Reprdef qmaGateEquiv : QMAGate ≃ ((ℕ ⊕ ℕ) ⊕ (ℕ × ℕ)) where toFun | .hadamard i => Sum.inl (Sum.inl i) | .phaseT i => Sum.inl (Sum.inr i) | .controlledNot i j => Sum.inr (i, j) invFun | Sum.inl (Sum.inl i) => .hadamard i | Sum.inl (Sum.inr i) => .phaseT i | Sum.inr (i, j) => .controlledNot i j left_inv g := by cases g <;> rfl right_inv g := by rcases g with (i | i) | ⟨i, j⟩ <;> rfldef qmaGateCodec : Codec QMAGate := BinaryEncoding.equiv (BinaryEncoding.sum (BinaryEncoding.sum natural natural) (pair natural natural)) qmaGateEquivstructure QMACircuit where work : ℕ witness : ℕ gates : List QMAGate deriving DecidableEq, Reprdef qmaCircuitEquiv : QMACircuit ≃ (ℕ × (ℕ × List QMAGate)) where toFun c := (c.work, c.witness, c.gates) invFun c := ⟨c.1, c.2.1, c.2.2⟩ left_inv c := by cases c; rfl right_inv c := by rcases c with ⟨n, w, gs⟩; rfldef qmaCircuitCodec : Codec QMACircuit := BinaryEncoding.equiv (pair natural (pair natural (BinaryEncoding.list qmaGateCodec))) qmaCircuitEquivdef QMAGate.WellFormed (n : ℕ) : QMAGate → Prop | .hadamard i => i < n | .phaseT i => i < n | .controlledNot i j => i < n ∧ j < n ∧ i ≠ jdef QMACircuit.WellFormed (c : QMACircuit) : Prop := c.witness ≤ c.work ∧ ∀ g ∈ c.gates, g.WellFormed (c.work + 1)def qmaHadamard : Matrix (Fin 2) (Fin 2) ℂ := bellScale • !![1, 1; 1, -1]def qmaPhaseT : Matrix (Fin 2) (Fin 2) ℂ := !![1, 0; 0, bellScale * (1 + Complex.I)]def qmaQubit (work index : ℕ) : Fin (work + 1) := ⟨index % (work + 1), Nat.mod_lt _ (Nat.succ_pos _)⟩def qmaControlledNot (work : ℕ) (control target : Fin (work + 1)) (s : SourceSpinBasis (work + 1)) : SourceSpinBasis (work + 1) := fun i => if i = target ∧ s control = 1 then Equiv.swap (0 : Fin 2) 1 (s i) else s idef qmaGateMatrix (work : ℕ) : QMAGate → Matrix (SourceSpinBasis (work + 1)) (SourceSpinBasis (work + 1)) ℂ | .hadamard i => sourceTensor (work + 1) (fun k => if k = qmaQubit work i then qmaHadamard else 1) | .phaseT i => sourceTensor (work + 1) (fun k => if k = qmaQubit work i then qmaPhaseT else 1) | .controlledNot i j => fun s t => if s = qmaControlledNot work (qmaQubit work i) (qmaQubit work j) t then 1 else 0def qmaCircuitMatrix (c : QMACircuit) : Matrix (SourceSpinBasis (c.work + 1)) (SourceSpinBasis (c.work + 1)) ℂ := c.gates.foldl (fun M g => qmaGateMatrix c.work g * M) 1def qmaInitialState (c : QMACircuit) (hc : c.WellFormed) (psi : EuclideanSpace ℂ (SourceSpinBasis c.witness)) : SourceSpinBasis (c.work + 1) → ℂ := fun s => if ∀ i : Fin (c.work + 1), c.witness ≤ i.val → s i = 0 then psi (fun i => s ⟨i.val, lt_of_lt_of_le i.isLt (hc.1.trans (Nat.le_succ _))⟩) else 0def qmaAcceptance (c : QMACircuit) (hc : c.WellFormed) (psi : EuclideanSpace ℂ (SourceSpinBasis c.witness)) : ℝ := ∑ s : SourceSpinBasis (c.work + 1), if s (Fin.last c.work) = 1 then Complex.normSq ((qmaCircuitMatrix c).mulVec (qmaInitialState c hc psi) s) else 0structure QuantumVerifier where generate : BitString → QMACircuit uniform : Turing.TM2ComputableInPolyTime id qmaCircuitCodec.encode generate size : Polynomial ℕ size_bound : ∀ x, (generate x).work + (generate x).gates.length ≤ size.eval x.length wellFormed : ∀ x, (generate x).WellFormedstructure PromiseProblem (α : Type) where yes : Set α no : Set α disjoint : @Disjoint (Set α) (@ChainCompletePartialOrder.toPartialOrder (Set α) (@ChainCompletePartialOrder.instOfCompleteLattice (Set α) (@CompleteBooleanAlgebra.toCompleteLattice (Set α) (@CompleteAtomicBooleanAlgebra.toCompleteBooleanAlgebra (Set α) (@Set.instCompleteAtomicBooleanAlgebra α))))) (@HeytingAlgebra.toOrderBot (Set α) (@Order.Frame.toHeytingAlgebra (Set α) (@CompleteDistribLattice.toFrame (Set α) (@CompleteBooleanAlgebra.toCompleteDistribLattice (Set α) (@CompleteAtomicBooleanAlgebra.toCompleteBooleanAlgebra (Set α) (@Set.instCompleteAtomicBooleanAlgebra α)))))) yes nosectiontheorem inQMA_two_atLeastTwo : Nat.AtLeastTwo (1 + 1) := @Nat.instAtLeastTwoHAddOfNat 1 (@Nat.instNeZeroSucc 0)theorem inQMA_three_atLeastTwo : Nat.AtLeastTwo (2 + 1) := @Nat.instAtLeastTwoHAddOfNat 2 (@Nat.instNeZeroSucc 1)attribute [local instance] inQMA_two_atLeastTwo inQMA_three_atLeastTwodef InQMA (P : PromiseProblem BitString) : Prop := ∃ V : QuantumVerifier, (∀ x ∈ P.yes, ∃ psi : EuclideanSpace ℂ (SourceSpinBasis (V.generate x).witness), ‖psi‖ = 1 ∧ 2 / 3 ≤ qmaAcceptance (V.generate x) (V.wellFormed x) psi) ∧ (∀ x ∈ P.no, ∀ psi : EuclideanSpace ℂ (SourceSpinBasis (V.generate x).witness), ‖psi‖ = 1 → qmaAcceptance (V.generate x) (V.wellFormed x) psi ≤ 1 / 3)endstructure PolynomialManyOne {α β : Type} (ea : α → BitString) (eb : β → BitString) (P : PromiseProblem α) (Q : PromiseProblem β) where map : α → β polynomialTime : Turing.TM2ComputableInPolyTime ea eb map maps_yes : ∀ x ∈ P.yes, map x ∈ Q.yes maps_no : ∀ x ∈ P.no, map x ∈ Q.nodef QMAHard {α : Type} (encoding : α → BitString) (Q : PromiseProblem α) : Prop := ∀ P : PromiseProblem BitString, InQMA P → Nonempty (PolynomialManyOne id encoding P Q)structure BinaryRational where numerator : ℤ denominator : ℕ deriving DecidableEq, Reprdef BinaryRational.value (q : BinaryRational) : ℚ := (q.numerator : ℚ) / q.denominatordef binaryRationalEquiv : BinaryRational ≃ (ℤ × ℕ) where toFun q := (q.numerator, q.denominator) invFun q := ⟨q.1, q.2⟩ left_inv q := by cases q; rfl right_inv q := by cases q; rfldef binaryRationalCodec : Codec BinaryRational := BinaryEncoding.equiv (pair integer natural) binaryRationalEquivabbrev Position := Coulomb.Spaceabbrev Configuration := Coulomb.Configurationabbrev SpinConfiguration := Coulomb.Spinsstructure NuclearData where nuclei : ℕ nuclei_pos : 0 < nuclei position : Fin nuclei → Fin 3 → ℚ distinct : Function.Injective position charge : Fin nuclei → ℕ charge_pos : ∀ a, 0 < charge a electrons : ℕ electrons_pos : 0 < electronsstructure UnitNuclearData where nuclei : ℕ nuclei_pos : 0 < nuclei position : Fin nuclei → Fin 3 → ℚ distinct : Function.Injective position electrons : ℕ electrons_pos : 0 < electronsdef UnitNuclearData.toNuclearData (d : UnitNuclearData) : NuclearData where nuclei := d.nuclei nuclei_pos := d.nuclei_pos position := d.position distinct := d.distinct charge := fun _ => 1 charge_pos := fun _ => Nat.zero_lt_one electrons := d.electrons electrons_pos := d.electrons_possectiontheorem realPosition_atLeastTwo : Nat.AtLeastTwo (1 + 1) := @Nat.instAtLeastTwoHAddOfNat 1 (@Nat.instNeZeroSucc 0)attribute [local instance] realPosition_atLeastTwodef realPosition (r : Fin 3 → ℚ) : Position := WithLp.toLp 2 (fun a => (r a : ℝ))endtheorem realPosition_injective : Function.Injective realPosition := by intro r s hrs funext a have h := congrArg (fun p : Position => p a) hrs change (r a : ℝ) = (s a : ℝ) at h exact_mod_cast hdef NuclearData.toNuclei (d : NuclearData) : Coulomb.Nuclei d.nuclei where nonempty := d.nuclei_pos position := fun a => realPosition (d.position a) distinct := realPosition_injective.comp d.distinct charge := fun a => (d.charge a : ℝ) charge_ge_one := by intro a exact_mod_cast d.charge_pos aabbrev FormState (n : ℕ) := {state : Coulomb.H1Vector n // Coulomb.Antisymmetric state}abbrev normSq {n : ℕ} (state : FormState n) := Coulomb.mass state.valabbrev kineticEnergy {n : ℕ} (state : FormState n) := Coulomb.kinetic state.valdef coulombForm (d : NuclearData) (state : FormState d.electrons) : ℝ := Coulomb.form d.toNuclei state.valdef unitCoulombForm (d : UnitNuclearData) (state : FormState d.electrons) : ℝ := coulombForm d.toNuclearData statedef groundEnergy (d : NuclearData) : EReal := sInf {e | ∃ state : FormState d.electrons, normSq state = 1 ∧ e = (coulombForm d state : EReal)}def unitGroundEnergy (d : UnitNuclearData) : EReal := sInf {e | ∃ state : FormState d.electrons, normSq state = 1 ∧ e = (unitCoulombForm d state : EReal)}structure BinaryPosition where x : BinaryRational y : BinaryRational z : BinaryRational deriving DecidableEq, Reprdef BinaryPosition.value (p : BinaryPosition) : Fin 3 → ℚ := ![p.x.value, p.y.value, p.z.value]def BinaryPosition.Valid (p : BinaryPosition) : Prop := 0 < p.x.denominator ∧ 0 < p.y.denominator ∧ 0 < p.z.denominatordef binaryPositionEquiv : BinaryPosition ≃ (BinaryRational × (BinaryRational × BinaryRational)) where toFun p := (p.x, p.y, p.z) invFun p := ⟨p.1, p.2.1, p.2.2⟩ left_inv p := by cases p; rfl right_inv p := by rcases p with ⟨x, y, z⟩; rfldef binaryPositionCodec : Codec BinaryPosition := BinaryEncoding.equiv (pair binaryRationalCodec (pair binaryRationalCodec binaryRationalCodec)) binaryPositionEquivstructure BinaryCoulomb where nuclei : List (BinaryPosition × ℕ) electrons : ℕ lower : BinaryRational upper : BinaryRational deriving DecidableEq, Reprdef binaryCoulombEquiv : BinaryCoulomb ≃ (List (BinaryPosition × ℕ) × (ℕ × (BinaryRational × BinaryRational))) where toFun d := (d.nuclei, d.electrons, d.lower, d.upper) invFun d := ⟨d.1, d.2.1, d.2.2.1, d.2.2.2⟩ left_inv d := by cases d; rfl right_inv d := by rcases d with ⟨ns, n, a, b⟩; rfldef binaryCoulombCodec : Codec BinaryCoulomb := BinaryEncoding.equiv (pair (BinaryEncoding.list (pair binaryPositionCodec natural)) (pair unary (pair binaryRationalCodec binaryRationalCodec))) binaryCoulombEquivstructure BinaryCoulomb.Valid (d : BinaryCoulomb) : Prop where nuclei_pos : 0 < d.nuclei.length electrons_pos : 0 < d.electrons positions : ∀ a : Fin d.nuclei.length, (d.nuclei.get a).1.Valid distinct : Function.Injective (fun a : Fin d.nuclei.length => (d.nuclei.get a).1.value) charge_pos : ∀ a : Fin d.nuclei.length, 0 < (d.nuclei.get a).2 lower_denominator : 0 < d.lower.denominator upper_denominator : 0 < d.upper.denominator gap : 1 ≤ d.upper.value - d.lower.valuedef BinaryCoulomb.toData (d : BinaryCoulomb) (h : d.Valid) : NuclearData where nuclei := d.nuclei.length nuclei_pos := h.nuclei_pos position a := (d.nuclei.get a).1.value distinct := h.distinct charge a := (d.nuclei.get a).2 charge_pos := h.charge_pos electrons := d.electrons electrons_pos := h.electrons_posstructure UnitCoulomb where nuclei : List BinaryPosition electrons : ℕ lower : BinaryRational upper : BinaryRational deriving DecidableEq, Reprdef unitCoulombEquiv : UnitCoulomb ≃ (List BinaryPosition × (ℕ × (BinaryRational × BinaryRational))) where toFun d := (d.nuclei, d.electrons, d.lower, d.upper) invFun d := ⟨d.1, d.2.1, d.2.2.1, d.2.2.2⟩ left_inv d := by cases d; rfl right_inv d := by rcases d with ⟨ns, n, a, b⟩; rfldef unitCoulombCodec : Codec UnitCoulomb := BinaryEncoding.equiv (pair (BinaryEncoding.list binaryPositionCodec) (pair unary (pair binaryRationalCodec binaryRationalCodec))) unitCoulombEquivstructure UnitCoulomb.Valid (d : UnitCoulomb) : Prop where nuclei_pos : 0 < d.nuclei.length electrons_pos : 0 < d.electrons positions : ∀ a : Fin d.nuclei.length, (d.nuclei.get a).Valid distinct : Function.Injective (fun a : Fin d.nuclei.length => (d.nuclei.get a).value) lower_denominator : 0 < d.lower.denominator upper_denominator : 0 < d.upper.denominator gap : 1 ≤ d.upper.value - d.lower.valuedef UnitCoulomb.toData (d : UnitCoulomb) (h : d.Valid) : UnitNuclearData where nuclei := d.nuclei.length nuclei_pos := h.nuclei_pos position a := (d.nuclei.get a).value distinct := h.distinct electrons := d.electrons electrons_pos := h.electrons_posdef binaryCoulombPromise : PromiseProblem BinaryCoulomb where yes := {d | ∃ h : d.Valid, groundEnergy (d.toData h) ≤ ((d.lower.value : ℝ) : EReal)} no := {d | ∃ h : d.Valid, ((d.upper.value : ℝ) : EReal) ≤ groundEnergy (d.toData h)} disjoint := by apply Set.disjoint_left.mpr rintro d ⟨h, hyes⟩ ⟨h', hno⟩ have hgap : d.lower.value < d.upper.value := by linarith [h.gap] have hgap' : ((d.lower.value : ℝ) : EReal) < ((d.upper.value : ℝ) : EReal) := by exact_mod_cast hgap exact (not_le_of_gt hgap') (hno.trans hyes)def unitCoulombPromise : PromiseProblem UnitCoulomb where yes := {d | ∃ h : d.Valid, unitGroundEnergy (d.toData h) ≤ ((d.lower.value : ℝ) : EReal)} no := {d | ∃ h : d.Valid, ((d.upper.value : ℝ) : EReal) ≤ unitGroundEnergy (d.toData h)} disjoint := by apply Set.disjoint_left.mpr rintro d ⟨h, hyes⟩ ⟨h', hno⟩ have hgap : d.lower.value < d.upper.value := by linarith [h.gap] have hgap' : ((d.lower.value : ℝ) : EReal) < ((d.upper.value : ℝ) : EReal) := by exact_mod_cast hgap exact (not_le_of_gt hgap') (hno.trans hyes)theorem unit_coulomb_qmaHard : QMAHard unitCoulombCodec.encode unitCoulombPromise := by sorrytheorem binary_coulomb_qmaHard : QMAHard binaryCoulombCodec.encode binaryCoulombPromise := by sorryend ContinuumCoulombendend OAI