Or just realize that all FOV algorithms are premature optimizations of the brute force 'draw a line from origin to every point within the AABB' algorithm. Oh, and if you're concerned with symmetry and wall lighting artifacts are undesirable, do *not* use Bresenham's line drawing algorithm, for what you are interested in (line of sight) use the 'supercover' variant.
[For TL;DR types, you can stop here.]
The advantage of just doing brute force is that it satisfies your criteria of symmetry, it does not have artifacts, and it is very simple to implement.
If your game runs slow, profile it, if the results show that FOV calculation is the bottleneck, then look at ways to speed it up. The best optimization is to not perform unnecessary FOV calcs in the first place*. If you still have a performance issue, then consider the following:
None of the 'improved' algorithms in common use fulfill the same contract, they relax the constraints, they no longer satisfy the symmetry invariant (and incidentally the wall artifact issue is part of this). That is, the improved field of view algorithms in common use solve a different problem. If the relaxed constraints are satisfactory for your use, fine, implement, profile, and you are most likely done.
If you do not want to solve a different problem, if you want to solve the original problem but with fewer calculations, and in less time, then consider classic routes to performance improvement, a memory for speed trade off. Use memoization to reduce the cost of map queries if that is a bottleneck. For a given order of evaluation, you can get the same end results without using any line drawing or any calculation besides simple point translation and perhaps a distance check, by precalculating the effect each individual cell position has on visibility within the bounds (effectively memoizing the 'cast_ray' function with an origin of {0,0}). You can use quadrant, or even octant, folding to reduce the memory requirements.**
Or, as Tilded noted above, you may be able to change the math of one of the common algorithms to achieve the same end result. For reasonable values of vision radius, I doubt you will see much difference in final runtime performance on modern desktop hardware. For mobile environments, try both and profile.
Irregardless of which algorithm you end up using, you may still be unsatisfied with the result in certain situations like, visibility at corners or with diagonal gaps. Consider evaluating the immediate surroundings (the neighbor cells) to detect those cases and doing a second, composite, FOV calc from the appropriate neighboring cell (perhaps of shorter range) to obtain a more satisfactory result.
I'll say it again. Do not use Bresenham's line algorithm for line of sight purposes, regardless of how many clueless idiots out there immediately recommend it as the 'obvious' solution. Use a 'supercover' variant which checks each and every cell the line actually passes through. Having been one of those clueless idiots in the past, and likely will be again in regards to other topics, no offense is intended.
*There is no reason (except if you have memory and cycles to throw away) to do full blown FOV calcs for anything other than the primary viewpoint. There are simpler solutions, even if you need to use a quadtree to reduce working sets.
**There is another step involved where you realize that you don't need to cast the lines (even in memoized form) at all. As long as you are walking the space in a 'closest first' manner, you only need to answer the question, "What cells are blocked by the current cell that the map query tells me is blocking further vision?". Solving for that answer reduces the order of the algorithm.