Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

z3-wasm support #19

Closed
rlisahuang opened this issue Jun 29, 2022 · 14 comments
Closed

z3-wasm support #19

rlisahuang opened this issue Jun 29, 2022 · 14 comments
Assignees
Labels
help wanted Extra attention is needed
Milestone

Comments

@rlisahuang
Copy link
Contributor

rlisahuang commented Jun 29, 2022

Context

I encountered some issues with getting the TypeScript bindings to work in Node.js. The idea is to break down a given code snippet (in the smt2 format) by line and obtain the output through Z3.eval_smtlib2_string. My main reference is this z3-wasm webpage, which uses our official WASM build. The way inputs are processed is detailed in their main.js file.

Problem with Node.js

Note that this website runs z3-wasm in the browser from the client side, while we want to run z3-wasm with Node.js from the server side. Therefore, their logic for running Z3 does not work in our scenario -- I had RuntimeErrors complaining about the inability to find z3-built.wasm. My implementation for running Z3 (currently commented out) can be found in website/src/remark/render-code-blocks.mjs in PR #18 .

Additional issue(s) with z3-wasm

I also noticed that several code snippets from our tutorial would not work in the web interface cited above. I wonder if this is a bug with the WASM build, or if there are additional API calls we should use instead for such code snippets. An example of snippet that does not work in the web interface:

(set-option print-success true) 
(set-option produce-unsat-cores true) ; enable generation of unsat cores
(set-option produce-models true) ; enable model generation
(set-option produce-proofs true) ; enable proof generation
(declare-const x Int)
(set-option produce-proofs false) ; error, cannot change this option after a declaration or assertion
(echo before reset)
(reset)
(set-option produce-proofs false) ; ok

I got a bunch of syntax errors when I ran it in that web interface.

@NikolajBjorner We would like some help from Kevin on the following issues:

  1. A simple example of running z3-wasm in Node.js with smt2-formatted inputs;
  2. The syntax errors I got from running code snippets from our tutorial in the existing web interface -- is it a bug, or are there ways around it?
@rlisahuang rlisahuang added the help wanted Extra attention is needed label Jun 29, 2022
@rlisahuang rlisahuang added this to the phase 1 milestone Jun 29, 2022
@NikolajBjorner
Copy link
Collaborator

The format should be:

(set-option :print-success true) 
(set-option :produce-unsat-cores true) ; enable generation of unsat cores
(set-option :produce-models true) ; enable model generation
(set-option :produce-proofs true) ; enable proof generation
(declare-const x Int)
(set-option :produce-proofs false) ; error, cannot change this option after a declaration or assertion
(echo "before reset")
(reset)
(set-option :produce-proofs false) ; ok

It is missing some : and some quotes.

It still doesn't work through the wasm front end. This is not specific to wasm, but because we are replicating the command-line interpreter functionality over the API. When you run z3.exe from the command-line it will be in a different state than the command-line interpreter over the interface. There we can't change the proof state.
Either I find a way to fix the command-line interpreter over the API to have similar behavior as the executable,
or we change this example,
or we bundle things to run the executable with a pipe and don't use the API for these examples.
Running an executable (compiled using wasm) is maybe possible in some mind-boggling dockerized virtual universe.

@NikolajBjorner
Copy link
Collaborator

Perhaps obvious: If there are syntax errors from z3 ask me (Kevin is two levels of indirection from z3 internals, but wasm connoisseur).

@NikolajBjorner
Copy link
Collaborator

Way to troubleshoot syntax errors over web:

  • repro using executable.
    • If syntax errors persist, then update example (or ask me how to update)
    • If executable doesnt' suffer from errors then it is wasm. Note that reading one line at a time is bad. One or more of online examples call z3 with one line at a time.

@pelikhan
Copy link
Member

pelikhan commented Jun 30, 2022 via email

@NikolajBjorner
Copy link
Collaborator

I have no clue how node.js works.
Here is a link to the action that creates the release
https://github.com/Z3Prover/z3/blob/master/.github/workflows/wasm-release.yml

@rlisahuang
Copy link
Contributor Author

I think the wasm-release.yml script you attached is used for building the JS/TS API with Node.js, not for running some Z3 examples with the API in Node.js. So in this case we might want to consult Kevin.

@rlisahuang
Copy link
Contributor Author

Can we simply run the z3 cli from node.js on the server?

child_process.spawn(path_to_the_Z3_binary, ["-smt2", path_to_input_file]) should do the job?

@pelikhan
Copy link
Member

you probably want to use child_process.exec which returns the output, but yes pretty much that. Recommend moving to creating subfolders for each sample rather files.

@NikolajBjorner
Copy link
Collaborator

What should be done with Github Action to accomplish this?

https://github.com/Z3Prover/z3/actions/runs/2585405315/workflow

@pelikhan
Copy link
Member

@rlisahuang can you split the node.js vs z3 formatting issues?

@bakkot
Copy link
Contributor

bakkot commented Jun 30, 2022

There is an example in the documentation for using the low-level API from node. Just replace '../../build/node' with 'z3-solver' and it should work.

Or if you want something which doesn't require typescript or building at all:

'use strict';
let { init } = require('z3-solver');

(async () => {
  let { em, Z3 } = await init();
  let config = Z3.mk_config();
  let ctx = Z3.mk_context_rc(config);
  Z3.del_config(config);
  // Z3.global_param_set('verbose', '10');

  console.log(await Z3.eval_smtlib2_string(ctx, `
    (declare-fun f (Int) Int)
    (declare-fun a () Int) ; a is a constant
    (declare-const b Int) ; syntax sugar for (declare-fun b () Int)
    (assert (> a 20))
    (assert (> b a))
    (assert (= (f 10) 1))
    (check-sat)
    (get-model)
  `));

  Z3.del_context(ctx);

  em.PThread.terminateAllThreads();
})().catch(e => {
  console.error('error', e);
  process.exit(1);
});

@pelikhan
Copy link
Member

Very useful. Do you have an example of running multiple eval_smtlib2_string concurrently -- or should we keep things sequential?

@bakkot
Copy link
Contributor

bakkot commented Jun 30, 2022

eval_smtlib2_string can't run concurrently in the current design. Gotta do one at a time.

@rlisahuang
Copy link
Contributor Author

Thanks @bakkot for the help! We are now able to run z3-wasm synchronously on the web.

Closing this issue for now and moving the conversations on mismatched behavior between z3-wasm and executable to a separate issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants