diff --git a/src/api/js/src/high-level/high-level.test.ts b/src/api/js/src/high-level/high-level.test.ts index f36291764e7..7d3038a7bfb 100644 --- a/src/api/js/src/high-level/high-level.test.ts +++ b/src/api/js/src/high-level/high-level.test.ts @@ -161,6 +161,19 @@ describe('high-level', () => { }); describe('booleans', () => { + it('can use pseudo-boolean constraints', async () => { + const { Bool, PbEq, Solver } = api.Context('main'); + const x = Bool.const('x'); + const y = Bool.const('y'); + + const solver = new Solver(); + solver.add(PbEq([x, y], [1, 1], 1)); + expect(await solver.check()).toStrictEqual('sat'); + + solver.add(x.eq(y)); + expect(await solver.check()).toStrictEqual('unsat'); + }); + it("proves De Morgan's Law", async () => { const { Bool, Not, And, Eq, Or } = api.Context('main'); const [x, y] = [Bool.const('x'), Bool.const('y')]; diff --git a/src/api/js/src/high-level/high-level.ts b/src/api/js/src/high-level/high-level.ts index 2c69848c3e2..f3bc51583a9 100644 --- a/src/api/js/src/high-level/high-level.ts +++ b/src/api/js/src/high-level/high-level.ts @@ -961,6 +961,57 @@ export function createApi(Z3: Z3Core): Z3HighLevel { } } + function PbEq(args: [Bool, ...Bool[]], coeffs: [number, ...number[]], k: number): Bool { + _assertContext(...args); + if (args.length !== coeffs.length) { + throw new Error('Number of arguments and coefficients must match'); + } + return new BoolImpl( + check( + Z3.mk_pbeq( + contextPtr, + args.map(arg => arg.ast), + coeffs, + k, + ), + ), + ); + } + + function PbGe(args: [Bool, ...Bool[]], coeffs: [number, ...number[]], k: number): Bool { + _assertContext(...args); + if (args.length !== coeffs.length) { + throw new Error('Number of arguments and coefficients must match'); + } + return new BoolImpl( + check( + Z3.mk_pbge( + contextPtr, + args.map(arg => arg.ast), + coeffs, + k, + ), + ), + ); + } + + function PbLe(args: [Bool, ...Bool[]], coeffs: [number, ...number[]], k: number): Bool { + _assertContext(...args); + if (args.length !== coeffs.length) { + throw new Error('Number of arguments and coefficients must match'); + } + return new BoolImpl( + check( + Z3.mk_pble( + contextPtr, + args.map(arg => arg.ast), + coeffs, + k, + ), + ), + ); + } + function ForAll>( quantifiers: ArrayIndexType, body: Bool, @@ -2883,6 +2934,9 @@ export function createApi(Z3: Z3Core): Z3HighLevel { Not, And, Or, + PbEq, + PbGe, + PbLe, ForAll, Exists, Lambda, diff --git a/src/api/js/src/high-level/types.ts b/src/api/js/src/high-level/types.ts index 45a06bda609..ca8b30ef0af 100644 --- a/src/api/js/src/high-level/types.ts +++ b/src/api/js/src/high-level/types.ts @@ -429,6 +429,15 @@ export interface Context { /** @category Operations */ Or(...args: Probe[]): Probe; + /** @category Operations */ + PbEq(args: [Bool, ...Bool[]], coeffs: [number, ...number[]], k: number): Bool; + + /** @category Operations */ + PbGe(args: [Bool, ...Bool[]], coeffs: [number, ...number[]], k: number): Bool; + + /** @category Operations */ + PbLe(args: [Bool, ...Bool[]], coeffs: [number, ...number[]], k: number): Bool; + // Quantifiers /** @category Operations */