How to get all models or all convex evaluation? - c++

I'm new to the Z3-Solver with API in C++ and want to solve a group of inequalities and find the results.
I've read the answer which written in Python and try to write it in C++, but it repeating prints one model.
5 <= x + y + z <= 16
AND -4 <= x - y <= 6
AND 1 <= y - z <= 3
AND -1 <= x - z <= 7
AND x >= 0 AND y >= 0 AND z >= 0
The inequalities were added into the solver, and have a lot of evaluations.
c is context and s is the solver.
vector<const char*> variables {"x", "y", "z"};
// ...
// till here, s was added into several constraints
while(s.check() == sat){
model m = s.get_model();
cout << m << "\n######\n";
expr tmp = c.bool_val(false);
for(int i = 0; i < variables.size(); ++ i){
tmp = tmp || (m[c.int_const(variables[i])] != c.int_const(variables[i]));
}
s.add(tmp);
}
And the result:
(define-fun z () Int
0)
(define-fun y () Int
2)
(define-fun x () Int
3)
######
(define-fun z () Int
0)
(define-fun y () Int
2)
(define-fun x () Int
3)
######
(define-fun z () Int
0)
...
And it just print one model. I'm not sure where is wrong.
How can I get all models or get one or more convex sets (such as {l1 <= x <= u1 and l2 <= x - y <= u2 and ...}), but not to traverse all evaluations.
BTW, there's a lot tutorials on python(such as this), where I can learn z3 in c++ as the example and api doc. is not easy to get started.

Your "model refutation" loop isn't quite correct. Since you didn't post your whole code, it's hard to tell if there might be other issues, but this is how I would go about it:
#include<vector>
#include"z3++.h"
using namespace std;
using namespace z3;
int main(void) {
context c;
expr_vector variables(c);
variables.push_back(c.int_const("x"));
variables.push_back(c.int_const("y"));
variables.push_back(c.int_const("z"));
expr x = variables[0];
expr y = variables[1];
expr z = variables[2];
solver s(c);
s.add(5 <= x+y+z);
s.add(x+y+z <= 16);
s.add(-4 <= x-y);
s.add(x-y <= 6);
s.add(-1 <= x-z);
s.add(x-z <= 7);
s.add(x >= 0);
s.add(y >= 0);
s.add(z >= 0);
while (s.check() == sat) {
model m = s.get_model();
cout << m << endl;
cout << "#######" << endl;
expr tmp = c.bool_val(false);
for(int i = 0; i < variables.size(); ++i) {
tmp = tmp || (variables[i] != m.eval(variables[i]));
}
s.add(tmp);
}
return 0;
}
This code runs and enumerates all the "concrete" models. From your question, I surmise you're also wondering if you can get "symbolic" models: That's not possible with an SMT solver. SMT solvers only produce concrete (i.e., all ground term) models, so if you need to generalize from them, you'll have to do that outside of the z3 boundary.

Related

Solving a dp problem from codeforces - Cut Ribbon

I was trying to solve this problem and from the comments section in the editorial, I was directed to the following solution :
#include <bits/stdc++.h>
using namespace std;
#define MAX(a,b,c) max(a,max(b,c))
int n,a,b,c,dp[4001];
int f(int x)
{
if (x == 0) return 0;
if (x < 0 || (x > 0 && x < a && x < b && x < c))
return 0xACCE97ED; // <- **I have doubt here**
if (!dp[x]) dp[x] = MAX(f(x-a),f(x-b),f(x-c)) + 1;
return dp[x];
}
int main()
{
cin >> n >> a >> b >> c;
memset(dp,0,sizeof(dp));
cout << f(n) << endl;
}
I wanted to know:
What is the need of the if statement that returns 0xACCE97ED for the test case:
4000 1 2 3. This test case dosen't work when that specific if statement is missing.
Why specifically 0xACCE97ED is being returned? Because when I tried to return any other number (say 9999), then the output is expected output + 9999.
if (x < 0 || (x > 0 && x < a && x < b && x < c))
return 0xACCE97ED; // -1395746835
Well looking at the dp function, it is basically maximizing values and this specific if statement is saying:
if x < 0
the length of the ribbon you cut is negative (which should be impossible)
or if x > 0 and x < a, b, c which means you can still cut X but all available sizes would result into having a ribbon of negative length
return 0xACCE97ED; return a random negative value which happens to spell out ACCEPTED because this state is invalid
And since the third if statement will try to get the max value, 0xACCE97ED will never be selected as the max value.
0xACCE97ED means "ACCEPTED" in the 1ee7 speech. nothing else specific about this value.
What is the need of the if statement that returns 0xACCE97ED for the test case: 4000 1 2 3
if (x < 0 || (x > 0 && x < a && x < b && x < c))
return 0xACCE97ED; // <- **I have doubt here**
because the function f is recursive, in the next line it calls itself:
if (!dp[x]) dp[x] = MAX(f(x-a),f(x-b),f(x-c)) + 1;
return dp[x];
with a smaller values for x so presumable it will eventually make that if statement true and will return "accepted" (0xACCE97ED).

How I can speed up my algorithm?

I'm solving some problems and I can't solve these one. I have to write a code where user enter a decimal number, and I need to count how many times that number starts with digit 1 in other numerous systems.
Here is algorithm:
for (int i = 3; i <= n; i++) {
int z = n;
while (z != 0) {
x = z % i;
z = z / i;
}
if (x == 1) {
brOsnova++;
}
}
You can accelerate it already by not checking the i's that verify
i <= n < 2*i since all of them will satisfy.
Therefore, check only for(int i = 3; i <= n/2; ++i) and then add (n+1)/2 to the final brOsnova.
I am sure it can be further accelerated and there must be some O(log(n)) algorithm, but maybe it would be far fetched... or a good candidate question for the algorithm tag.
Instead of the loop, use this:
x = x - ((x / i) * i);
if (x == 1)
{
...
}
This only works for integer maths.

Could someone tell me any different way to make this code faster?

The code runs correctly and it does what it is supposed to do, but I was told I could make it faster by using Boolean expressions instead but would not really know where to insert them here. The problem is:
Given a sequence of n points with their coordinates, write a program remote, which calculates the value of the smallest remoteness of a point, which is outside the square. A point is outside the square, if it is neither inner to the square, nor belongs to square contour. If there are no points outside the square, your program has to output 0.
Constraints:
1 ≤ n ≤ 10000 and 1 ≤ a ≤ 1000 ;
Example:
Input:
5 4
1 2
4 6
-3 2
-2 2
4 -1
Output: 5
Could someone suggest me any technique to make the code more efficient?
int remote(int x, int y) {
int z = abs(x) + abs(y);
return z;
}
int main() {
int n, a;
int x;
int y;
cin >> n >> a;
int z=20001;
for (int i = 1; i <= n; i++) {
cin >> x >> y;
if (x > a / 2 || y > a / 2) {
if (z > remote(x, y)) {
z = remote(x, y);
}
}
}
cout << z <<endl;
return 0;
}
For one, you are calling remote twice (in some cases) needlessly.
Consider using this:
#include <algorithm>
z = std::max(z, remote(x, y));
This will also shorten and clarify the code.
Also, it's possible the divisions are slow. Try (after profiling!) replacing
x > a / 2 || y > a / 2
by
(x << 1) > a || (y << 1) > a
Note #Donnie & others claims in the comments that compilers will do the latter optimization, and they are probably correct.
I would like to show you the timings on my machine:
Version 1:
for (int i = 1; i <= n; i++) {
cin >> x >> y;
if (x > a / 2 || y > a / 2) {
if (z > remote(x, y)) {
z = remote(x, y);
}
}
}
Version 2:
for (int i = 1; i <= n; i++) {
cin >> x >> y;
/* if (x > a / 2 || y > a / 2) {
if (z > remote(x, y)) {
z = remote(x, y);
}
}
*/
}
For n=10^5, compiled with -O3 both yield 60ms. Compiled without optimization: both 60ms.
First step for optimizing is to know where your program spends time. Reading/parsing the data is the bottle neck.
You could speed up it a little bit by adding as first line to your main:
ios_base::sync_with_stdio(false);
On my machine I'm down to 20ms.
1) Assign a temporary value to the remote function:
if (x > a / 2 || y > a / 2)
{
const int r = remote(x,y);
if (z > r)
{
z = r;
}
}
2) Replace the call to remote with the contents of remote, removing the overhead of a function call:
if (x > a / 2 || y > a / 2)
{
const int r = abs(x) + abs(y);
if (z > r)
{
z = r;
}
}
3) Replace a / 2 with a constant temporary variable:
const int midpoint = a >> 1;
if (x > midpoint || y > midpoint)
4) Change compiler optimization level to high - for speed.
5) The bottleneck is now in the input statement. Any gain by optimizing the remainder of the loop is wasted by the Input time. There is no more Return On Investment for further changes.

Dynamic Programming: Calculate all possible end positions for a list of consecutive jumps

The problem consists in calculate all possible end positions and how many combinations exist for each one.
Given a start position x=0, a length m of the track and a list of jumps. Return the number of possible ends for each position on the interval [-m/2,+m/2]. The jumps must be done in the same order as given but it could be done in negative or positive way.
For example:
L = 40
jumps = 10, 10
Solution:
-20 : 1 (-10, -10)
0 : 2 (-10,+10 & +10,-10)
20 : 1 (+10,+10)
(The output needed is only the pair "position : #combinations")
I did it with a simple recursion, and the result is OK.
But in large sets of data, the execution time is few minutes or hours.
I know that with dynamic programming I can have a solution in few seconds, but I don't know how can I apply dynamic in this case.
There's my actual recursive function:
void escriuPosibilitats(queue<int> q, map<int,int> &res, int posicio, int m) {
int salt = q.front();
q.pop();
if(esSaltValid(m,posicio,-salt)) {
int novaPosicio = posicio - salt;
if(q.empty()) {
res[novaPosicio]++;
} else {
escriuPosibilitats(q,res,novaPosicio,m);
}
}
if(esSaltValid(m,posicio,salt)) {
int novaPosicio = posicio + salt;
if(q.empty()) {
res[novaPosicio]++;
} else {
escriuPosibilitats(q,res,novaPosicio,m);
}
}
}
Where q is the queue of the remaining jumps.
Where res is the parcial solution.
Where posicio is the actual position.
Where m is the length of the track.
Where esSaltValid is a function that checks if the jump is valid in the range of the track length.
PD: Sorry for my english level. I tried to improve my question! Thanks =)
You can use the following idea. Let dp[x][i] be the number of ways to arrive to the position x using until the jump i. Then the answer would be dp[x][N] for each x, and where N is the number of jumps. Even more, you can realize that this dp depends only on the previous row, and then you can simply dp[x] and save the next row in some auxiliary array, and then replace it in each iteration. The code would be something like this:
const int MOD = (int)(1e8+7);
const int L = 100;
int N = 36;
int dx[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
int dp[L+1];
int next[L+1];
int main() {
int shift = L/2; // to handle negative indexes
dp[shift] = 1; // the initial position has one way to arrive, since you start there
for (int i = 0; i < N; ++i) { // for each jump size
for (int x = -L/2; x <= L/2; ++x) { // for each possible position
if (-L/2 <= x + dx[i] && x + dx[i] <= L/2) // positive jump
next[x + shift] = (next[x + shift] + dp[x + dx[i] + shift]) % MOD;
if (-L/2 <= x - dx[i] && x - dx[i] <= L/2) // negative jump
next[x + shift] = (next[x + shift] + dp[x - dx[i] + shift]) % MOD;
}
for (int x = -L/2; x <= L/2; ++x) { // update current dp to next and clear next
dp[x+shift] = next[x+shift];
next[x+shift] = 0;
}
}
for (int x = -L/2; x <= L/2; ++x) // print the result
if (dp[x+shift] != 0) {
cout << x << ": " << dp[x+shift] << '\n';
}
}
Of course, in case L is too big to handle, you can compress the state space and save the results in a map, and not in an array. The complexity of the approach is O(L*N). Hope it helped.
EDIT: just compute everything modulo 1e8+7 and that's it.

Finding MAX of numbers without conditional IF statements c++ [duplicate]

This question already has answers here:
Mathematically Find Max Value without Conditional Comparison
(18 answers)
Closed 9 years ago.
So i have too get two numbers from user input, and find the max of the two numbers without using if statements.
The class is a beginner class, and we have too use what we already know. I kinda worked something out, but it only works if the numbers are inputted with the max number first.
#include <iostream>
using namespace std;
int main()
{
int x = 0, y = 0, max = 0;
int smallest, largest;
cout << "Please enter 2 integer numbers, and i will show you which one is larger: ";
cin >> x >> y;
smallest = (x < y == 1) + (x - 1);
smallest = (y < x == 1) + (y - 1);
largest = (x < y == 1) + (y - 1);
largest = (y > x == 1) + (x + 1 - 1);
cout << "Smallest: " << smallest << endl;
cout << "Largest: " << largest << endl;
return 0;
}
Thats what i have so far, but after putting different test data in, i found out it only works for numbers such as 4,5 or 6,7. But numbers with more then 2 spaces between eachother they dont such as, 4,8 or 5, 7. Any help would be appreciated.
I saw this question in Cracking the Coding interview book.
Let’s try to solve this by “re-wording” the problem We will re-word the problem until we get something that has removed all if statements
Rewording 1: If a > b, return a; else, return b
Rewording 2: If (a - b) is negative, return b; else, return a
Rewording 3: If (a - b) is negative, let k = 1; else, let k = 0 Return a - k * (a - b)
Rewording 4: Let c = a - b Let k = the most significant bit of c Return a - k * c
int getMax(int a, int b) {
int c = a - b;
int k = (c >> ((sizeof(int) * CHAR_BIT) - 1)) & 0x1;
int max = a - k * c;
return max;
}
Source: http://www.amazon.com/Cracking-Coding-Interview-Programming-Questions/dp/098478280X
Edit: This code works even when a-b overflows.
Let k equal the sign of a-b such that if a-b >=0, then k is 1, else k=0.Let q be the inverse of k. Above code overflows when a is positive or b is negative, or the other way around. If a and b have different signs, then we want the k to equal sign(a).
/* Flips 1 to 0 and vice-versa */
public static int flip(int bit){
return 1^bit;
}
/* returns 1 if a is positive, and 0 if a is negative */
public static int sign(int a){
return flip((a >> ((sizeof(int) * CHAR_BIT) - 1)) & 0x1);
}
public static int getMax(int a, int b){
int c = a - b;
int sa = sign(a-b); // if a>=0, then 1 else 0
int sb = sign(a-b); // if b>=1, then 1 else 0
int sc = sign(c); // depends on whether or not a-b overflows
/* If a and b have different signs, then k = sign(a) */
int use_sign_of_a = sa ^ sb;
/* If a and b have the same sign, then k = sign(a - b) */
int use_sign_of_c = flip(sa ^ sb);
int k = use_sign_of_a * sa + use_sign_of_c * sc;
int q = flip(k); //opposite of k
return a * k + b * q;
}
Here is a funny solution:
int max_num = (x>y)*x + (y>=x)*y;
Assuming that you have covered bitwise operators already you can do this:
max = a-((a-b)&((a-b)>>(sizeof(int)*8-1)));
This is based off of the solution from Mathematically Find Max Value without Conditional Comparison that #user93353 pointed out in the comments above.
This may be overkill if you really are just trying to avoid if statements, not comparisons in general.
You can try this code to find max and min for two input variables.
((a > b) && (max = a)) || (max=b);
((a < b) && (min = a)) || (min=b);
For three input variables you can use similar method like this:
int main()
{
int a = 10, b = 9 , c = 8;
cin >> a >> b >> c;
int max = a, min = a;
// For Max
((a > b) && (a > c) && (max=a)) ||
((b > c) && (b > a) && (max=b)) ||
(max=c) ;
// For min
((a < b) && (a < c) && (min=a)) ||
((b < c) && (b < a) && (min=b)) ||
(min=c) ;
cout << "max = " << max;
cout << "and min = " << min;
return 1;
}
One run is:
:~$ ./a.out
1
2
3
max = 3 and min = 1
Edit
Thanks to #Tony D: This code will fail for negative numbers.
One may try this for negative numbers for two inputs to find max(not sure for this):
((a > b) && ( a > 0 && (max = a))) || ((b > a) && (max = b)) || (max = a);