bool transposition_based_synthesis( circuit& circ, const binary_truth_table& spec,
      properties::ptr settings, properties::ptr statistics )
  {
    // Settings parsing
    // Run-time measuring
    timer<properties_timer> t;

    if ( statistics )
    {
      properties_timer rt( statistics );
      t.start( rt );
    }

    unsigned bw = spec.num_outputs();
    circ.set_lines( bw );
    copy_metadata( spec, circ );

    std::map<unsigned, unsigned> values_map;

    for ( binary_truth_table::const_iterator it = spec.begin(); it != spec.end(); ++it )
    {
      binary_truth_table::cube_type in( it->first.first, it->first.second );
      binary_truth_table::cube_type out( it->second.first, it->second.second );

      values_map.insert( std::make_pair( truth_table_cube_to_number( in ), truth_table_cube_to_number( out ) ) );
    }

    // Set of cycles
    std::vector<std::vector<unsigned> > cycles;

    while ( !values_map.empty() )
    {
      unsigned start_value = values_map.begin()->first; // first key in values_map

      std::vector<unsigned> cycle;
      unsigned target = start_value;

      do
      {
        cycle += target;
        unsigned old_target = target;
        target = values_map[target];
        values_map.erase( old_target ); // erase this entry
      } while ( target != start_value );

      cycles += cycle;
    }

    for ( auto& cycle : cycles )
    {
      unsigned max_distance = 0u;
      unsigned max_index = 0u;

      for ( unsigned i = 0u; i < cycle.size(); ++i )
      {
        unsigned first = cycle.at(i);
        unsigned second = cycle.at( (i + 1u) % cycle.size() );

        unsigned distance = hamming_distance( first, second );

        if ( distance > max_distance )
        {
          max_distance = distance;
          max_index = i;
        }
      }

      std::vector<unsigned> tmp;
      std::copy( cycle.begin() + ( max_index + 1u ), cycle.end(), std::back_inserter( tmp ) );
      std::copy( cycle.begin(), cycle.begin() + ( max_index + 1u ), std::back_inserter( tmp ) );
      std::copy( tmp.begin(), tmp.end(), cycle.begin() );
      std::reverse( cycle.begin(), cycle.end() );
    }

    // TODO create transpositions function
    for ( auto& cycle : cycles )
    {
      for ( unsigned i = 0u; i < cycle.size() - 1; ++i )
      {
        circuit transposition_circ( spec.num_inputs() );

        unsigned first = cycle.at(i);
        unsigned second = cycle.at( (i + 1) % cycle.size() );

        boost::dynamic_bitset<> first_bits( spec.num_inputs(), first );
        boost::dynamic_bitset<> second_bits( spec.num_inputs(), second );

        transposition_to_circuit( transposition_circ, first_bits, second_bits );

        append_circuit( circ, transposition_circ);
      }
    }

    return true;
  }
Beispiel #2
0
int Bits::first_bit(Spot p) {
	return first_bits(bits[idx_of_spot(p)]);
}
Beispiel #3
0
void ywing_process_hinge(Bits* bits, Spot hinge, std::vector<Spot>* double_spots, std::vector<YWing>* ret) {
	int hinge_bits = bits->bit_of_spot(hinge);

	for(int i=0; i < double_spots->size(); i++) {
		Spot wing1 = (*double_spots)[i];
		int wing1_bits = bits->bit_of_spot(wing1);

		// only consider wings that aren't the hinge, but are visible to the hinge, and have exactly 1 candidate in common with the hinge
		if(spot_equal(wing1,hinge) || !spot_visible(wing1,hinge) || count_bits(hinge_bits & wing1_bits) != 1 ) {
			continue;
		}

		for(int j=i+1; j < double_spots->size(); j++) {
			Spot wing2 = (*double_spots)[j];
			int wing2_bits = bits->bit_of_spot(wing2);

			// only consider wings that aren't the hinge, but are visible to the hinge, and have exactly 1 candidate in common with the hinge and the other wing
			if(spot_equal(wing2,hinge) || !spot_visible(wing2,hinge) || count_bits(hinge_bits & wing2_bits) != 1 || count_bits(wing1_bits & wing2_bits) != 1 || count_bits(hinge_bits & wing1_bits & wing2_bits) != 0) {
				continue;
			}

			// now we have two unique wings that can see the hinge, and each has only one candidate shared between each other

			// the candidate we can exclude is the shared candidate between the two wings
			int shared_candidate = first_bits(wing1_bits & wing2_bits);

			// determine all spots that are visible to both wing1 and wing2 (same row, column, or box)
			std::vector<Spot> shared_spots;
			for(int ia=0; ia < 9; ia++) {
				for(int ib=0; ib < 9; ib++) {
					Spot p = Spot(ia,ib);

					// exclude the hinge and wing spots
					if(spot_equal(p,hinge) || spot_equal(p,wing1) || spot_equal(p,wing2)) { continue; }

					if((p.row == wing1.row || p.col == wing1.col || boxid_of_spot(p) == boxid_of_spot(wing1)) && (p.row == wing2.row || p.col == wing2.col || boxid_of_spot(p) == boxid_of_spot(wing2))) {
						shared_spots.push_back(p);
					}
				}
			}

			// NOTE: potentially more-efficient version commented out, didn't figure out the best way to make this compile.
			// if(wing1.row == wing2.row) {
			// 	shared_spots = spots_union(shared_spots,spots_of_row(wing1.row));
			// }
			// if(wing1.col == wing2.col) {
			// 	shared_spots = spots_union(shared_spots,spots_of_col(wing1.col));
			// }
			// if(boxid_of_spot(wing1) == boxid_of_spot(wing2)) {
			// 	shared_spots = spots_union(shared_spots,spots_of_box(boxid_of_spot(wing1)));
			// }
			// remove any excluded spots (hinge,wings) from our list
			// std::vector<Spot> excluded_spots;
			// excluded_spots.push_back(hinge);
			// excluded_spots.push_back(wing1);
			// excluded_spots.push_back(wing2);
			// shared_spots = spots_subtract(shared_spots,excluded_spots);

			// candidate array (if necessary)
			std::vector<int> candidates;
			candidates.push_back(shared_candidate);

			std::vector<Target> targets;
			for(int k=0; k < shared_spots.size(); k++) {
				Spot target_spot = shared_spots[k];
				if(bits->has_candidate(target_spot,shared_candidate) && bits->count_candidates(target_spot) > 1) {
					targets.push_back(Target(target_spot, candidates, 0));
				}
			}
			if(targets.size() > 0) {
				KeyRank keyrank;
				std::vector<Spot> wings;
				wings.push_back(wing1);
				wings.push_back(wing2);
				ret->push_back(YWing(targets, keyrank.keys, hinge, wings));
			}
		}
	}
}