示例#1
0
bool if2k_lua_interpreter::if_parse_cached_url(
  const char *url, 
  const char *cachefile,
  bool ignore_remote_if_local_exists
  )
{
  jdk_remote_buf remote_lua_code(
    cachefile,
    url,
    settings.get("further_proxy"), 
    1024*1024, 
    ignore_remote_if_local_exists
    );
  
  if( remote_lua_code.check_and_grab() )
  {
    jdk_synchronized(mutex);	
    int oldtop = lua_gettop(get_l());
    bool r = parse_buf( remote_lua_code.get_buf() )==0;
    lua_settop(get_l(),oldtop);
    return r;
  }
  
  return false;
}
示例#2
0
uint32_t ti89_get_long(uint32_t adr) 
{
	// RAM access
	if(IN_BOUNDS(0x000000, adr, 0x1fffff))
	{
		return get_l(tihw.ram, adr, RAM_SIZE_TI89 - 1);
	}

    // FLASH access
	else if(IN_BOUNDS(0x200000, adr, 0x5fffff))
	{
		return get_l(tihw.rom, adr, ROM_SIZE_TI89 - 1) | wsm.ret_or;
	}
	
	// memory-mapped I/O
    else if(IN_BOUNDS(0x600000, adr, 0x6fffff))
	{
       return io_get_long(adr);
	}

	// memory-mapped I/O (hw2)
	else if(IN_RANGE(adr, 0x700000, IO2_SIZE_TI89))
	{
		return io2_get_long(adr);
	}

    return 0x14141414;
}
示例#3
0
文件: mem89.c 项目: TC01/gcc4ti
uint32_t ti89_get_long(uint32_t adr) 
{
	// RAM access
	if(IN_BOUNDS(0x000000, adr, 0x1fffff))
	{
		return get_l(ram, adr, RAM_SIZE_TI89 - 1);
	}

    // FLASH access
	else if(IN_BOUNDS(0x200000, adr, 0x5fffff))
	{
		return get_l(rom, adr, ROM_SIZE_TI89 - 1);
	}

    return 0x14141414;
}
示例#4
0
bool if2k_lua_interpreter::if_cgi_put(
  const jdk_string &cmd,
  if2k_lua_web_response  &ret,
  const jdk_string &client_ip,
  const jdk_http_request_header &request_header,
  const jdk_dynbuf &putcontents,
  const jdk_settings_text &cgiparams
  )
{
  jdk_debug_block( "if2k_lua_interpreter::if_cgi_put()" );
  ret.clear();
  jdk_str<1024> func_name = "if_cgi_put_";
  func_name.cat( cmd );
  jdk_log( JDK_LOG_DEBUG4, "%s", func_name.c_str() );
  jdk_synchronized(mutex);
  jdk_lua_call(
    get_l(),
    func_name.c_str(),
    ret,
    client_ip,
    request_header,
    putcontents,
    cgiparams
    );
  return ret.header.is_valid();
}
示例#5
0
bool if2k_lua_interpreter::parse_builtin( const char *fname )
{
  jdk_bindir *bin = jdk_bindir_find( "if2k_lua_files", fname );
  if( bin )
  {
    jdk_log_debug2( "found builtin %s", fname );
    jdk_synchronized(mutex);	
    int oldtop = lua_gettop(get_l());
    parse_buf( bin->data, bin->length );
    lua_settop(get_l(),oldtop);
    return true;
  }
  else
  {
    jdk_log( JDK_LOG_ERROR, "can't find builtin script %s", fname);
    return false;
  }	
}
示例#6
0
void if2k_lua_interpreter::update()
{
  jdk_debug_block( "if2k_lua_interpreter::update()" );
  
  {
    jdk_synchronized( mutex );
    jdk_lua_setglobal( get_l(), "settings", settings );
  }
  jdk_log_debug2( "if2k_lua_interpreter settings set" );
  {
    jdk_synchronized( mutex);
    parse_builtin( "if2k_lua_init.luac" );
    
    int oldtop = lua_gettop( get_l());
    jdk_lua_call( get_l(), "if_run" );
    lua_settop( get_l(),oldtop);
  }
  jdk_log_debug2( "if2k_lua_interpreter if_run() complete" );		
  
  jdk_str<128> lua_builtin_init = settings.get("lua_builtin_init");
  if( !lua_builtin_init.is_clear() )
  {
    jdk_log_debug1( "if2k_lua_interpreter parsing builtin: %s", lua_builtin_init.c_str() );
    jdk_synchronized( mutex);
    parse_builtin( lua_builtin_init.c_str() );
  }
  
  jdk_remote_buf remote_lua_code( settings, "lua_init", 1024*1024, false );
  
  if( remote_lua_code.check_and_grab() )
  {
    jdk_synchronized( mutex);	
    int oldtop = lua_gettop( get_l());
    parse_buf( remote_lua_code.get_buf() );
    lua_settop( get_l(),oldtop);
    jdk_log_debug1( "if2k_lua_interpreter remote buf parsed" );		
  }
  
  jdk_str<4096> lua_command = settings.get("lua_command");
  if( !lua_command.is_clear() )
  {
    jdk_synchronized( mutex);		
    
    jdk_log_debug2( "if2k_lua_interpreter parsing lua_command: %s", lua_builtin_init.c_str() );
    
    int oldtop = lua_gettop( get_l());
    parse_string( lua_command.c_str() );
    lua_settop( get_l(),oldtop);
  }	
  
  
}
示例#7
0
bool if2k_lua_interpreter::if_parse_url( const char *url )
{
  jdk_dynbuf response;
  jdk_http_response_header response_header;
  
  if( jdk_http_get(
        url,
        &response,
        1024*512,
        &response_header,
        settings.get("further_proxy").c_str(),
        false
        )==200 )
  {
    jdk_synchronized(mutex);	
    
    int oldtop = lua_gettop(get_l());
    bool r = parse_buf( response )==0;
    lua_settop(get_l(),oldtop);
    return r;
  }
  
  return false;
}
示例#8
0
bool if2k_lua_interpreter::if_url_override(
  jdk_buf &ret, 
  const jdk_string &client_ip,
  const jdk_http_request_header &request_header 
  )
{
  jdk_debug_block( "if2k_lua_interpreter::if_url_override()" );
  ret.clear();
  jdk_synchronized(mutex);
  jdk_lua_call(
    get_l(),
    "if_url_override", 
    ret, 
    client_ip,
    request_header 
    );
  return ret.get_data_length()>0;
}
示例#9
0
bool if2k_lua_interpreter::if_url_error(
  const jdk_string &error_name,
  if2k_lua_web_response &ret,
  const jdk_string &client_ip,
  const jdk_http_request_header &request_header 
  )
{
  jdk_str<1024> lua_func("if_url_error_");
  lua_func.cat( error_name );
  
  jdk_debug_block( "if2k_lua_interpreter::if_url_error()" );
  ret.clear();
  jdk_synchronized(mutex);
  jdk_lua_call(
    get_l(),
    lua_func.c_str(), 
    ret, 
    client_ip,
    request_header 
    );
  return ret.contents.get_data_length()>0;
}
示例#10
0
bool if2k_lua_interpreter::if_url_blocked(
  jdk_string_url &redirect_url, 
  const jdk_string &client_ip,
  const jdk_http_request_header &request_header,
  int reason,
  const jdk_string &match
  )
{
  jdk_debug_block( "if2k_lua_interpreter::if_url_blocked()" );
  redirect_url.clear();
  jdk_synchronized(mutex);
  jdk_lua_call(
    get_l(), 
    "if_url_blocked", 
    redirect_url, 
    client_ip,
    request_header,
    reason,
    match
    );
  return redirect_url.len()>0;
}
示例#11
0
bool if2k_lua_interpreter::if_cgi_post(
  const jdk_string &cmd,
  if2k_lua_web_response  &ret,
  const jdk_string &client_ip,
  const jdk_http_request_header &request_header,
  const jdk_dynbuf &postparams
  )
{
  jdk_debug_block( "if2k_lua_interpreter::if_cgi_post()" );
  ret.clear();
  jdk_str<1024> func_name = "if_cgi_post_";
  func_name.cat( cmd );
  jdk_synchronized(mutex);
  jdk_lua_call(
    get_l(),
    func_name.c_str(),
    ret,
    client_ip,
    request_header,
    postparams
    );
  return ret.header.is_valid();
}
示例#12
0
文件: mem89tm.c 项目: debrouxl/tiemu
uint32_t ti89t_get_long(uint32_t adr) 
{
	// RAM access
	if(IN_BOUNDS(0x000000, adr, 0x03ffff) ||
	   IN_BOUNDS(0x200000, adr, 0x23ffff) ||
	   IN_BOUNDS(0x400000, adr, 0x43ffff))
	{
		return get_l(tihw.ram, adr, 0x03ffff);
	}

	// FLASH access
    else if(IN_BOUNDS(0x800000, adr, 0xbfffff))			
	{
		// use FlashReadLong due to Epson Device ID
		return FlashReadLong(adr);
	}

	// memory-mapped I/O
    else if(IN_BOUNDS(0x600000, adr, 0x6fffff))
	{
       return io_get_long(adr);
	}

	// memory-mapped I/O (hw2)
	else if(IN_RANGE(adr, 0x700000, IO2_SIZE_TI89T))
	{
		return io2_get_long(adr);
	}

	// memory-mapped I/O (hw3)
	else if(IN_RANGE(adr, 0x710000, IO3_SIZE_TI89T))
	{
		return io3_get_long(adr);
	}

    return 0x14141414;
}
示例#13
0
if2k_lua_interpreter::if2k_lua_interpreter(
  const jdk_settings &settings_, 
  int stack_size_
  )
  : 
  jdk_lua_interpreter(stack_size_),	
  settings(settings_),
  reload_settings_trigger(false)
{
  jdk_debug_block( "if2k_lua_interpreter" );
  jdk_synchronized( mutex );
  jdk_lua_regfunc(
    get_l(), 
    "url_encode", 
    jdk_lua_thunk1<lua_url_encode,jdk_string_url,jdk_string_url > 
    );
  
  jdk_lua_regfunc(
    get_l(),
    "url_decode",
    jdk_lua_thunk1<lua_url_decode,jdk_string_url,jdk_string_url >
    );
  
  jdk_lua_regfunc(
    get_l(),
    "html_encode",
    jdk_lua_thunk1<lua_html_encode,jdk_dynbuf,jdk_dynbuf >
    );
  
  jdk_lua_regfunc(
    get_l(),
    "html_decode",
    jdk_lua_thunk1<lua_html_decode,jdk_dynbuf,jdk_dynbuf >
    );
  
  jdk_lua_regfunc(
    get_l(),
    "if_reload",
    jdk_lua_thunk0_noreturn<lua_if_reload>
    );
  
  jdk_lua_regfunc(
    get_l(),
    "if_get_settings",
    jdk_lua_thunk0<lua_if_get_settings,jdk_dynbuf>
    );	
  
  jdk_lua_regfunc(
    get_l(),
    "if_update_settings",
    jdk_lua_thunk1<lua_if_update_settings,int,jdk_dynbuf>
    );	
  
  jdk_lua_regfunc(
    get_l(),
    "if_parse_builtin",
    jdk_lua_thunk1<lua_if_parse_builtin,int,jdk_str<256> >
    );
  
  jdk_lua_regfunc(
    get_l(),
    "if_parse_url",
    jdk_lua_thunk1<lua_if_parse_url,int,jdk_string_url >
    );
  
  jdk_lua_regfunc(
    get_l(),
    "if_parse_cached_url",
    jdk_lua_thunk3<lua_if_parse_cached_url,int,jdk_string_url,jdk_string_url,int  >
    );
  
}
	real PseudoBoolean<real>::minimize_reduction_M(vector<label>& x, int& nlabelled) const
	{
		//
		// Compute a large enough value for M
		//
		real M = 0;
		for (auto itr=aijkl.begin(); itr != aijkl.end(); ++itr) {
			real a = itr->second;
			M += abs(a);
		}
		for (auto itr=aijk.begin(); itr != aijk.end(); ++itr) {
			real a = itr->second;
			M += abs(a);
		}
		for (auto itr=aij.begin(); itr != aij.end(); ++itr) {
			real a = itr->second;
			M += abs(a);
		}
		for (auto itr=ai.begin(); itr != ai.end(); ++itr) {
			real a = itr->second;
			M += abs(a);
		} 

		// Copy of the polynomial. Will contain the reduced polynomial
		PseudoBoolean<real> pb = *this;
		// Number of variables (will be increased
		int n = nvars();
		int norg = n;

		//
		// Reduce the degree-4 terms 
		//
		double M2 = M;
		for (auto itr=pb.aijkl.begin(); itr != pb.aijkl.end(); ++itr) {
			int i = get_i(itr->first);
			int j = get_j(itr->first);
			int k = get_k(itr->first);
			int l = get_l(itr->first);
			real a = itr->second;

			// a*xi*xj*xk*xl  will be converted to
			// a*xi*xj*z + M( xk*xl - 2*xk*z - 2*xl*z + 3*z )
			int z = n++;

			pb.add_monomial(i,j,z, a);

			pb.add_monomial(k,l,M);
			pb.add_monomial(k,z, -2*M);
			pb.add_monomial(l,z, -2*M);
			pb.add_monomial(z, 3*M);

			M2 += a + 4*M;
		}
		
		// Remove all degree-4 terms.
		pb.aijkl.clear();

		//
		// Reduce the degree-3 terms
		//
		for (auto itr=pb.aijk.begin(); itr != pb.aijk.end(); ++itr) {
			int i = get_i(itr->first);
			int j = get_j(itr->first);
			int k = get_k(itr->first);
			real a = itr->second;

			// a*xi*xj*xk  will be converted to
			// a*xi*z + M( xj*xk -2*xj*z -2*xk*z + 3*z )
			int z = n++;

			pb.add_monomial(i,z, a);

			pb.add_monomial(j,k,M2);
			pb.add_monomial(j,z, -2*M2);
			pb.add_monomial(k,z, -2*M2);
			pb.add_monomial(z, 3*M2);
		}

		// Remove all degree-3 terms.
		pb.aijk.clear();

		//
		// Minimize the reduced polynomial
		//
		vector<label> xtmp(n,-1);
		real bound = pb.minimize(xtmp, HOCR);

		nlabelled = 0;
		for (int i=0;i<norg;++i) {
			x.at(i) = xtmp[i];
			if (x[i] >= 0) {
				nlabelled++;
			}
		}

		return bound;
	}
	real PseudoBoolean<real>::minimize_reduction(vector<label>& x, int& nlabelled) const
	{
		index nVars = index( x.size() );
		// Here it is important that all indices appear as pairs 
		// in aij or ai
		ASSERT_STR( nvars() <= nVars , "x too small");

		PBF<real, 4> hocr;
		map<int,bool> var_used;

		for (auto itr=ai.begin(); itr != ai.end(); ++itr) {
			int i = itr->first;
			real a = itr->second;
			hocr.AddUnaryTerm(i, 0, a);
			var_used[i] = true;
		}

		for (auto itr=aij.begin(); itr != aij.end(); ++itr) {
			int i = get_i(itr->first);
			int j = get_j(itr->first);
			real a = itr->second;
			hocr.AddPairwiseTerm(i,j, 0,0,0, a);
			var_used[i] = true;
			var_used[j] = true;
		}

		for (auto itr=aijk.begin(); itr != aijk.end(); ++itr) {
			int i = get_i(itr->first);
			int j = get_j(itr->first);
			int k = get_k(itr->first);
			real a = itr->second;
			int ind[] = {i,j,k};
			real E[8] = {0,0,0,0, 0,0,0,0};
			E[7] = a;
			hocr.AddHigherTerm(3, ind, E);
			var_used[i] = true;
			var_used[j] = true;
			var_used[k] = true;
		}

		for (auto itr=aijkl.begin(); itr != aijkl.end(); ++itr) {
			int i = get_i(itr->first);
			int j = get_j(itr->first);
			int k = get_k(itr->first);
			int l = get_l(itr->first);
			real a = itr->second;
			int ind[] = {i,j,k,l};
			real   E[16] = {0,0,0,0, 0,0,0,0,
			                0,0,0,0, 0,0,0,0};
			E[15] = a;
			hocr.AddHigherTerm(4, ind, E);
			var_used[i] = true;
			var_used[j] = true;
			var_used[k] = true;
			var_used[l] = true;
		}

		index nOptimizedVars = hocr.maxID() + 1;

		PBF<real,2> qpbf;
		hocr.toQuadratic(qpbf); 
		hocr.clear(); 
		QPBO<real> qpbo(nVars, qpbf.size(), err_function_qpbo); 
		convert(qpbo, qpbf);
		qpbo.MergeParallelEdges();
		qpbo.Solve();
		qpbo.ComputeWeakPersistencies();

		nlabelled = 0;
		for (int i=0; i < nOptimizedVars; ++i) {
			if (var_used[i] || x.at(i)<0) {
				x[i] = qpbo.GetLabel(i);
			}
			if (x[i] >= 0) {
				nlabelled++;
			}
		}

		// These variables were not part of the minimization
		ASSERT(nVars >= nOptimizedVars);
		nlabelled += nVars - nOptimizedVars;

		real energy = constant + qpbo.ComputeTwiceLowerBound()/2;
		//double energy = eval(x); //Only when x is fully labelled
		return energy;
	}
	real PseudoBoolean<real>::minimize_reduction_fixetal(vector<label>& x, int& nlabelled) const
	{
		int n = index( x.size() );

		// Work with a copy of the coefficients
		map<triple, real> aijk  = this->aijk;
		//map<pair, real> aij  = this->aij;
		//map<int, real> ai  = this->ai;
		//real constant = this->constant;

		// The quadratic function we are reducing to
		int nedges = int( aij.size() + aijk.size() + aijkl.size() + 1000 );
		int nvars  = int( n + aijkl.size() + aijk.size() + 1000 );
		QPBO<real> qpbo(nvars, nedges, err_function_qpbo);
		qpbo.AddNode(n);

		map<int,bool> var_used;

		//
		// Step 1: reduce all positive higher-degree terms
		//

		// Go through the variables one by one and perform the 
		// reductions of the quartic terms

		//for (int ind=0; ind<n; ++ind) {

		//	// Collect all terms with positive coefficients
		//	// containing variable i
		//	real alpha_sum = 0;

		//	// Holds new var
		//	int y = -1;

		//	for (auto itr=aijkl.begin(); itr != aijkl.end(); ++itr) {
		//		int i = get_i(itr->first);
		//		int j = get_j(itr->first);
		//		int k = get_k(itr->first);
		//		int l = get_l(itr->first);
		//		real a = itr->second;

		//		// We only have to test for ind==i because of the 
		//		// order we process the indices
		//		if (ind==i && a > 0) {
		//			alpha_sum += a;

		//			// Add term of degree 3
		//			aijk[ make_triple(j,k,l) ]  += a;

		//			// Add negative term of degree 4
		//			// -a*y*xj*xk*xl
		//			if (y<0) y = qpbo.AddNode();
		//			int z = qpbo.AddNode();
		//			qpbo.AddUnaryTerm(z, 0, 3*a);
		//			qpbo.AddPairwiseTerm(z,y, 0,0,0, -a);
		//			qpbo.AddPairwiseTerm(z,j, 0,0,0, -a);
		//			qpbo.AddPairwiseTerm(z,k, 0,0,0, -a);
		//			qpbo.AddPairwiseTerm(z,l, 0,0,0, -a);
		//		}
		//	}

		//	for (auto itr=aijk.begin(); itr != aijk.end(); ++itr) {
		//		int i = get_i(itr->first);
		//		int j = get_j(itr->first);
		//		int k = get_k(itr->first);
		//		real a = itr->second;

		//		// We only have to test for ind==i because of the 
		//		// order we process the indices
		//		if (ind==i && a > 0) {
		//			alpha_sum += a;

		//			// Add term of degree 2
		//			qpbo.AddPairwiseTerm(j,k, 0,0,0, a);

		//			// Add negative term of degree 3
		//			// -a*y*xj*xk
		//			if (y<0) y = qpbo.AddNode();
		//			int z = qpbo.AddNode();
		//			qpbo.AddUnaryTerm(z, 0, 2*a);
		//			qpbo.AddPairwiseTerm(z,y, 0,0,0, -a);
		//			qpbo.AddPairwiseTerm(z,j, 0,0,0, -a);
		//			qpbo.AddPairwiseTerm(z,k, 0,0,0, -a);
		//		}
		//	}

		//	if (alpha_sum > 0) {
		//		// Add the new quadratic term
		//		qpbo.AddPairwiseTerm(y,ind, 0,0,0, alpha_sum);
		//	}
		//}

		//
		// This code should be equivalent to the commented
		// block above, but faster
		//

		vector<real> alpha_sum(n, 0);
		vector<int>  y(n, -1);

		for (auto itr=aijkl.begin(); itr != aijkl.end(); ++itr) {
			int i = get_i(itr->first);
			int j = get_j(itr->first);
			int k = get_k(itr->first);
			int l = get_l(itr->first);
			real a = itr->second;

			if (a > 0) {
				alpha_sum[i] += a;

				// Add term of degree 3
				aijk[ make_triple(j,k,l) ]  += a;

				// Add negative term of degree 4
				// -a*y*xj*xk*xl
				if (y[i]<0) y[i] = qpbo.AddNode();
				int z = qpbo.AddNode();
				qpbo.AddUnaryTerm(z, 0, 3*a);
				qpbo.AddPairwiseTerm(z,y[i], 0,0,0, -a);
				qpbo.AddPairwiseTerm(z,j, 0,0,0, -a);
				qpbo.AddPairwiseTerm(z,k, 0,0,0, -a);
				qpbo.AddPairwiseTerm(z,l, 0,0,0, -a);
			}

			var_used[i] = true;
			var_used[j] = true;
			var_used[k] = true;
			var_used[l] = true;
		}

		for (auto itr=aijk.begin(); itr != aijk.end(); ++itr) {
			int i = get_i(itr->first);
			int j = get_j(itr->first);
			int k = get_k(itr->first);
			real a = itr->second;

			if (a > 0) {
				alpha_sum[i] += a;

				// Add term of degree 2
				qpbo.AddPairwiseTerm(j,k, 0,0,0, a);
				//aij[ make_pair(j,k) ] += a;

				// Add negative term of degree 3
				// -a*y*xj*xk
				if (y[i]<0) y[i] = qpbo.AddNode();
				/*int z = qpbo.AddNode();
				qpbo.AddUnaryTerm(z, 0, 2*a);
				qpbo.AddPairwiseTerm(z,y[i], 0,0,0, -a);
				qpbo.AddPairwiseTerm(z,j, 0,0,0, -a);
				qpbo.AddPairwiseTerm(z,k, 0,0,0, -a);*/
				aijk[ make_triple(y[i],j,k) ] += -a;
			}

			var_used[i] = true;
			var_used[j] = true;
			var_used[k] = true;
		}

		// No need to continue with the lower degree terms

		//for (auto itr=aij.begin(); itr != aij.end(); ++itr) {
		//	int i = get_i(itr->first);
		//	int j = get_j(itr->first);
		//	real& a = itr->second;

		//	if (a > 0) {
		//		alpha_sum[i] += a;

		//		// Add term of degree 1
		//		ai[ j ] += a;

		//		// Add negative term of degree 2
		//		// -a*y*xj
		//		if (y[i]<0) y[i] = qpbo.AddNode();
		//		aij[ make_pair(y[i],j) ] += -a;

		//		// Now remove this term
		//		a = 0;
		//	}
		//}

		//for (auto itr=ai.begin(); itr != ai.end(); ++itr) {
		//	int i =itr->first;
		//	real& a = itr->second;

		//	if (a > 0) {
		//		alpha_sum[i] += a;

		//		// Add term of degree 0
		//		constant += a;

		//		// Add negative term of degree 1
		//		// -a*y*xj
		//		if (y[i]<0) y[i] = qpbo.AddNode();
		//		ai[ y[i] ] += -a;

		//		// Now remove this term
		//		a = 0;
		//	}
		//}


		for (int i=0;i<n;++i) {
			if (alpha_sum[i] > 0) {
				// Add the new quadratic term
				qpbo.AddPairwiseTerm(y[i],i, 0,0,0, alpha_sum[i]);
			}
		}


		//
		// Done with reducing all positive higher-degree terms
		//

		// Add all negative quartic terms
		for (auto itr=aijkl.begin(); itr != aijkl.end(); ++itr) {
			real a = itr->second;
			if (a < 0) {
				int i = get_i(itr->first);
				int j = get_j(itr->first);
				int k = get_k(itr->first);
				int l = get_l(itr->first);

				int z = qpbo.AddNode();
				qpbo.AddUnaryTerm(z, 0, -3*a);
				qpbo.AddPairwiseTerm(z,i, 0,0,0, a);
				qpbo.AddPairwiseTerm(z,j, 0,0,0, a);
				qpbo.AddPairwiseTerm(z,k, 0,0,0, a);
				qpbo.AddPairwiseTerm(z,l, 0,0,0, a);
			}
		}

		// Add all negative cubic terms
		for (auto itr=aijk.begin(); itr != aijk.end(); ++itr) {
			real a = itr->second;
			if (a < 0) {
				int i = get_i(itr->first);
				int j = get_j(itr->first);
				int k = get_k(itr->first);

				int z = qpbo.AddNode();
				qpbo.AddUnaryTerm(z, 0, -2*a);
				qpbo.AddPairwiseTerm(z,i, 0,0,0, a);
				qpbo.AddPairwiseTerm(z,j, 0,0,0, a);
				qpbo.AddPairwiseTerm(z,k, 0,0,0, a);
			}
		}


		// Add all quadratic terms
		for (auto itr=aij.begin(); itr != aij.end(); ++itr) {
			real a = itr->second;
			int i = get_i(itr->first);
			int j = get_j(itr->first);
			qpbo.AddPairwiseTerm(i,j, 0,0,0, a);

			var_used[i] = true;
			var_used[j] = true;
		}

		// Add all linear terms
		for (auto itr=ai.begin(); itr != ai.end(); ++itr) {
			real a = itr->second;
			int i = itr->first;
			qpbo.AddUnaryTerm(i, 0, a);

			var_used[i] = true;
		}

		qpbo.MergeParallelEdges();
		qpbo.Solve();
		qpbo.ComputeWeakPersistencies();

		nlabelled = 0;
		for (int i=0; i<n; ++i) {
			if (var_used[i] || x.at(i)<0) {
				x[i] = qpbo.GetLabel(i);
			}
			if (x[i] >= 0) {
				nlabelled++;
			}
		}

		real energy = constant + qpbo.ComputeTwiceLowerBound()/2;

		return energy;
	}